Pregunta

Tengo un problema extraño al eliminar registros usando linq, mi sospecha es que tiene algo que ver con la variable de rango (llamada source). Después de eliminar un registro, todos los objetivos de un cliente se recuperan mediante la siguiente declaración:

var q = from source in unitOfWork.GetRepository<db_Target>().Find()
  where source.db_TargetBase.db_Person.fk_Customer == customerID
  select source.FromLinq();

donde FromLinq está en método de extensión en db_target:

public static Target FromLinq(this db_Target source)
{
    return new Target
    {
        id = source.id,
        LastModified = source.db_TargetBase.LastModified,
        ...
     }
}

Cuando se elimina un registro, se eliminan tanto db_Target como db_TargetBase. Cuando, por ejemplo, dos usuarios están eliminando registros, linq intenta recuperar un registro para el usuario2 que es eliminado por el usuario1, causando un bloqueo en la línea LastModified = source.db_TargetBase.LastModified porque null es return new Target.

Cuando se utiliza el siguiente código, el problema no se produce y solo se recuperan los registros no eliminados:

var q = from source in unitOfWork.GetRepository<db_Target>().Find()
    where source.db_TargetBase.db_Person.fk_Customer == customerID
    select new Target
    {
        id = source.id,
        LastModified = source.db_TargetBase.LastModified,
        ...
    };

Esto genera dos preguntas:

  1. ¿Qué está pasando aquí? ¿Estoy haciendo una copia de la variable de rango <=> porque la estoy usando en un método de extensión?
  2. ¿Cómo puedo " wrap " el código <=>? Estoy usando esto en varios lugares y no quiero copiarlo cada vez. Haciendo que mi código sea más difícil de mantener.

TIA,

JJ

¿Fue útil?

Solución

En el primer conjunto de código, dado que el inicializador utiliza un método no traducible (extensión u otro), no se puede traducir, por lo que se ejecuta localmente.

En el segundo conjunto de código: el inicializador está representado por una expresión elementinit, que se traduce (examine / compare la cláusula select del sql generado para la prueba).


si desea ajustar esto, necesita tener un Expression<Func<db_Target, Target>> que cualquiera pueda tomar y usar en su consulta. Afortunadamente, eso es fácil de hacer:

public Expression<Func<db_Target, Target>> GetFromLinqExpressionForTarget()
{
  return
    source => new Target
    {
      id = source.id,
      LastModified = source.db_TargetBase.LastModified,
      ...
    }
}

Que puede usarse así:

var FromLinq = GetFromLinqExpressionForTarget();
var q =
(
   from source in ...
   ...
   ...
   select source
).Select(FromLinq);

Ahora ... realmente estoy haciendo una suposición aquí y solo estoy aproximadamente 60% seguro de que mi respuesta es correcta. Entonces, si alguien quiere confirmar esto, eso me alegrará el día. :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top