使用 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_Target
和 db_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,
...
};
这产生了两个问题:
- 这里发生了什么? 我是否复制范围变量
source
因为我在扩展方法中使用它?
- 如何“包装”
返回新的 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:
- What is happening here? Am I making a copy of the range variable
source
because I'm using it in a extention method?
- 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
发布评论
评论(1)
在第一组代码中 - 由于初始化程序存在一个不可翻译的方法(扩展或其他),因此它无法被翻译 - 因此它在本地运行。
在第二组代码中 - 初始化程序由 elementinit 表达式表示,该表达式被翻译(检查/比较生成的 sql 的 select 子句以进行证明)。
如果你想包装它,你需要有一个任何人都可以在查询中获取和使用的
Expression>
。 幸运的是,这很容易做到:可以像这样使用:
现在...我真的在这里猜测,并且只有大约 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:Which may be used like so:
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. :)