LinqToSql strange behaviour(LinqToSql 奇怪的行为)
问题描述
我有以下代码:
var tagToPosts = (from t2p in dataContext.TagToPosts
join t in dataContext.Tags on t2p.TagId equals t.Id
select new { t2p.Id, t.Name });
//IQueryable tag2postsToDelete;
foreach (Tag tag in tags)
{
Debug.WriteLine(tag);
tagToPosts = tagToPosts.Where(t => t.Name != tag.Name);
}
IQueryable tagToPostsToDelete = (from t2p in dataContext.TagToPosts
join del in tagToPosts on t2p.Id equals del.Id
select t2p);
dataContext.TagToPosts.DeleteAllOnSubmit(tagToPostsToDelete);
其中 tags
是一个 List
- 由构造函数创建的标签列表,因此它们没有 id.我运行代码,在 Debug 线上放置一个刹车点,然后等待几个周期.然后我将 tagToPosts.ToList() 放在 Watch 窗口中以执行查询.在 SQL 探查器中,我可以看到以下查询:
where tags
is a List<Tag>
- list of tags created by constructor, so they have no id.
I run the the code putting a brakepoint on line with Debug and wait for a few cycles to go. Then I put tagToPosts.ToList() in the Watch window for query to execute.
In SQL profiler I can see the following query:
exec sp_executesql N'SELECT [t0].[Id], [t1].[Name]
FROM [dbo].[tblTagToPost] AS [t0]
INNER JOIN [dbo].[tblTags] AS [t1] ON [t0].[TagId] = [t1].[Id]
WHERE ([t1].[Name] @p0) AND ([t1].[Name] @p1) AND ([t1].[Name] @p2)',N'@p0 nvarchar(4),@p1 nvarchar(4),@p2 nvarchar(4)',@p0=N'tag3',@p1=N'tag3',@p2=N'tag3'
我们可以看到每个参数参数都有一个循环中最后一个tag.Name
的值.你知道如何解决这个问题并让循环添加 Where
和每个 tyme 的新条件吗?我可以看到 IQueryable 在执行之前只存储指向变量的指针.
We can see every parameter parameter have the value of last tag.Name
in a cycle.
Have you any idea on how to get arout this and get cycle to add Where
with new condition every tyme? I can see IQueryable stores only pointer to variable before execution.
推荐答案
将您的 foreach
更改为:
foreach (Tag tag in tags){
var x = tag.Name;
tagToPosts = tagToPosts.Where(t => t.Name != x);
}
这背后的原因是惰性求值和变量捕获.基本上,您在 foreach
语句中所做的是不是过滤结果,因为它看起来像.您正在构建依赖于要执行的某些变量的表达式树.需要注意的是,实际变量是在表达式树中捕获的,而不是捕获时的值.由于变量 tag
每次都会被使用(并且它的作用域是整个 foreach
,所以它不会在每次迭代结束时超出作用域),它被捕获对于表达式的每个部分,最后一个值将用于所有 出现.解决方案是使用一个临时变量,它的作用域在 foreach 中,因此它会在每次迭代和下一次迭代时超出范围,它将被视为新变量.
The reason behind this is lazy evaluation and variable capturing. Basically, what you are doing in the foreach
statement is not filtering out results as it might look like. You are building an expression tree that depends on some variables to execute. It's important to note that the actual variables are captured in that expression trees, not their values at the time of capture. Since the variable tag
is used every time (and it's scope is the whole foreach
, so it won't go out of scope at the end of each iteration), it's captured for every part of the expression and the last value will be used for all of its occurrences. The solution is to use a temporary variable which is scoped in the foreach so it'll go out of scope at each iteration and it the next iteration, it'll be considered a new variable.
这篇关于LinqToSql 奇怪的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:LinqToSql 奇怪的行为


基础教程推荐
- 覆盖 Json.Net 中的默认原始类型处理 2022-01-01
- 创建属性设置器委托 2022-01-01
- 我什么时候应该使用 GC.SuppressFinalize()? 2022-01-01
- C# - 如何列出发布到 ASPX 页面的变量名称和值 2022-01-01
- 使用 SED 在 XML 标签之间提取值 2022-01-01
- Page.OnAppearing 中的 Xamarin.Forms Page.DisplayAlert 2022-01-01
- 从 VB6 迁移到 .NET/.NET Core 的最佳策略或工具 2022-01-01
- 如何使用OpenXML SDK将Excel转换为CSV? 2022-01-01
- C# - 将浮点数转换为整数...并根据余数更改整数 2022-01-01
- 当键值未知时反序列化 JSON 2022-01-01