linq'范围变量'问题

时间:2009-06-18 08:18:31

标签: linq linq-to-sql null

使用linq删除记录时遇到一个奇怪的问题,我怀疑它与范围变量(名为source)有关。删除记录后,使用以下语句检索客户的所有目标:

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

其中FromLinq是db_target上的扩展方法:

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

删除记录后,db_Targetdb_TargetBase都会被删除。例如,当两个用户正在删除记录时,linq尝试检索user1删除的记录,由user1删除,导致LastModified = source.db_TargetBase.LastModified行崩溃,因为db_TargetBasenull。< / p>

使用以下代码时,不会发生问题,只检索未删除的记录:

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,
        ...
    };

这会产生两个问题:

  1. 这里发生了什么?我是否在制作范围变量source的副本,因为我在扩展方法中使用它?
  2. 如何“包装”return new Target代码?我在多个地方使用它,不想每次都复制它。使我的代码更难维护。
  3. TIA,

    JJ

1 个答案:

答案 0 :(得分:1)

在第一组代码中 - 由于初始化程序存在一个不可翻译的方法(扩展名或其他方法),因此无法翻译 - 因此它在本地运行。

在第二组代码中 - 初始化程序由elementinit表达式表示,该表达式被翻译(检查/比较生成的sql的select子句以进行证明)。


如果你想包装它,你需要有一个Expression<Func<db_Target, Target>>,任何人都可以在它的查询中抓取并使用它。幸运的是,这很容易做到:

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

可以这样使用:

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

现在......我真的在这里猜测,只有大约60%的人对我的回答是正确的。因此,如果有人想要证实这一点,那将是我的一天。 :)