none
Problema al guardar valor de un registro RRS feed

  • Pregunta

  • Hola a todos! Estoy con un proyecto de gestión de reclamos, y a la hora de guardar un reclamo necesito buscar el último número (atributo, no id), sumarle 1 y guardarlo. El tema es que por ejemplo, si hay 10 personas registrando reclamos a la vez, habría problemas a la hora de ir a buscar ese numero y guardar el valor correcto. Me comentaron algo sobre control de concurrencia, pero no tengo conocimientos al respecto. Alguna idea? muchas gracias de antemano! Saludos!
    jueves, 6 de septiembre de 2018 13:24

Respuestas

  • Si lo quieres hacer desde EF, tienes que usar un TransactionScope para lanzar la transaccion, y dentro meter la lectura y actualizacion. Mas o menos seria algo parecido a lo que te pongo a continuacion, pero logicamewnte tienes que cambiar los nombres de objetos por los tuyos:

    using System.Transactions;
    //...
    
    using (TransactionScope tran = new TransactionScope())
    {
        var max = (from t in context.MiTabla select t.Campo).Max();
        MiTabla mt = new MiTabla { campo = max+1, ... };
        context.Mitabla.Add(mt);
        context.SaveChanges();
        tran.Complete();
    }
    
    

    al codigo anterior tendras que agregarle un "if" para considerar el caso especial en que la tabla este completamente vacia y por lo tanto el Max devuelva NULL. Es decir, no puedes sumarle 1 al ultimo valor si no existe ningun ultimo valor.

    jueves, 6 de septiembre de 2018 15:28
  • El ejemplo depende del tipo de tecnologia cliente de acceso a datos que estes usando en tu aplicacion. Si lo fueras a hacer desde el lado servidor SQL seria asi:

    declare @ultimo int
    begin tran
    select @ultimo=isnull(MAX(campo),0) from laTabla
    insert into laTabla(campo, ...) values(@ultimo+1, ...)
    commit

    Si lo necesitas desde codigo cliente hay que ver que codigo cliente usas. No da igual si estas usando, por ejemplo, llamadas directas a ADO.NET, o un ORM tal como Entity Framework; de hecho, ni siquiera has mencionado el lenguaje de programacion que utilizas.

    jueves, 6 de septiembre de 2018 14:54
  • hola

    Para el control de concurrencia se usa un campo timespan, aqui

     Control Concurrencia

    explico sobre el tema

    pero basicamente si cuando vayas actualizar el dato debes validar si cambio el timespan, si lo hizo no actualizas he informas para que el cliente actualice los datos y decida si cambiar o no

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 6 de septiembre de 2018 16:33

Todas las respuestas

  • Si el numero lo asignas justo al final, una vez completado todo el proceso, entonces lo que puedes hacer es inicar una transaccion, buscar el ultimo numero, incrementarlo y grabarlo, y completar la transaccion. De esa manera la transaccion mantiene la tabla bloqueada mientras ejecutas esas dos sentencias y no hay problema en caso de recibir dos peticiones simultaneas (salvo que una de ella se retrasara unas milesimas de segundo mientras se completa la anterior).

    El problema vendria en caso de que necesites primero presentarle el numero al usuario, esperar a que rellene el resto de los datos, y luego grabar el numero. En ese caso si que habria problemas de concurrencia, que no se pueden resolver mediante una simple transaccion.

    jueves, 6 de septiembre de 2018 14:30
  • Hola Alberto! gracias por tu respuesta. Y de acuerdo al número, recién lo muestro una vez guardado el reclamo, así que no habría problemas. ¿De dónde podría sacar un ejemplo de un caso como este? tienes algún link, algo? Saludos
    jueves, 6 de septiembre de 2018 14:39
  • El ejemplo depende del tipo de tecnologia cliente de acceso a datos que estes usando en tu aplicacion. Si lo fueras a hacer desde el lado servidor SQL seria asi:

    declare @ultimo int
    begin tran
    select @ultimo=isnull(MAX(campo),0) from laTabla
    insert into laTabla(campo, ...) values(@ultimo+1, ...)
    commit

    Si lo necesitas desde codigo cliente hay que ver que codigo cliente usas. No da igual si estas usando, por ejemplo, llamadas directas a ADO.NET, o un ORM tal como Entity Framework; de hecho, ni siquiera has mencionado el lenguaje de programacion que utilizas.

    jueves, 6 de septiembre de 2018 14:54
  • Disculpa mi ignorancia, estoy utilizando C# con entity framework  y algo de Linq...
    • Editado AguFortini jueves, 6 de septiembre de 2018 15:14
    jueves, 6 de septiembre de 2018 15:13
  • Si lo quieres hacer desde EF, tienes que usar un TransactionScope para lanzar la transaccion, y dentro meter la lectura y actualizacion. Mas o menos seria algo parecido a lo que te pongo a continuacion, pero logicamewnte tienes que cambiar los nombres de objetos por los tuyos:

    using System.Transactions;
    //...
    
    using (TransactionScope tran = new TransactionScope())
    {
        var max = (from t in context.MiTabla select t.Campo).Max();
        MiTabla mt = new MiTabla { campo = max+1, ... };
        context.Mitabla.Add(mt);
        context.SaveChanges();
        tran.Complete();
    }
    
    

    al codigo anterior tendras que agregarle un "if" para considerar el caso especial en que la tabla este completamente vacia y por lo tanto el Max devuelva NULL. Es decir, no puedes sumarle 1 al ultimo valor si no existe ningun ultimo valor.

    jueves, 6 de septiembre de 2018 15:28
  • hola

    Para el control de concurrencia se usa un campo timespan, aqui

     Control Concurrencia

    explico sobre el tema

    pero basicamente si cuando vayas actualizar el dato debes validar si cambio el timespan, si lo hizo no actualizas he informas para que el cliente actualice los datos y decida si cambiar o no

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 6 de septiembre de 2018 16:33