linq“范围变量” 问题

发布于 2024-07-24 16:38:32 字数 1315 浏览 3 评论 0 原文

使用 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 尝试检索 user2 被 user1 删除的记录,导致 LastModified = source.db_TargetBase.LastModified 行崩溃,因为 db_TargetBase null

当使用以下代码时,不会出现问题,并且仅检索未删除的记录:

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. 如何“包装”返回新的 Target 代码? 我在多个地方使用它,不想每次都复制它。 使我的代码更难维护。

蒂亚,

JJ

I have a strange problem when deleteting records using linq, my suspicion is that it has something to do with the range variable (named source). After deleting a record all targets for a customer are retrieved using the following statement:

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

where FromLinq is in extention method on db_target:

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

When a record is deleted both db_Target and db_TargetBase are deleted. When, for example, two users are deleting records, linq tries to retrieve a record for user2 which is deleted by user1, causing a crash on the LastModified = source.db_TargetBase.LastModified line because db_TargetBase is null.

When using the following code the problem does not occure and only the non-deleted records are retrieved:

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

This spawns two questions:

  1. What is happening here? Am I making a copy of the range variable source because I'm using it in a extention method?
  2. How can I "wrap" the return new Target code? I am using this in multiple places and do not want to copy it every time. Making my code harder to maintain.

TIA,

JJ

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

智商已欠费 2024-07-31 16:38:32

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

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


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

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% 的信心我的答案是正确的。 所以如果有人想证实这一点,那我就开心了。 :)

In the first set of code - since the initializer lives an a non-translatable method (extension or otherwise), it cannot be translated - so it is run locally.

In the second set of code - the initializer is represented by an elementinit expression, which is translated (examine/compare the select clause of the generated sql for proof).


if you want to wrap this, you need to have an Expression<Func<db_Target, Target>> that anyone can grab and use in thier query. Fortunately, that's easy to do:

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

Which may be used like so:

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

Now ... I'm really running on a guess here and am only about 60% confident that my answer is correct. So if someone wants to confirm this, that'll make my day. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文