本地序列不能在查询运算符的 LINQ to SQL 实现中使用,但 Contains() 运算符除外
Posted
技术标签:
【中文标题】本地序列不能在查询运算符的 LINQ to SQL 实现中使用,但 Contains() 运算符除外【英文标题】:Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator 【发布时间】:2011-12-31 03:45:54 【问题描述】:我在我的项目中使用 LINQ,我的代码是:
var SE = from c in Shop.Sections
join c1 in obj.SectionObjects on c.SectionId equals c1.SectionId
select c;
dataGridView1.DataSource = SE;
但我在dataGridView1.DataSource = SE;
行中遇到了这个错误
错误信息是:
。
【问题讨论】:
将鼠标悬停在 Shop.Sections 上并告诉我们它的类型。然后将鼠标悬停在 obj.SectionObjects 上并告诉我们它的类型。 【参考方案1】:您不能在 SQL 源和本地源之间使用 Join。您需要先将 SQL 数据导入内存,然后才能加入它们。在这种情况下,您并没有真正进行连接,因为您只从第一个集合中获取元素,您想要的是一个 select...where...selectid in 查询,您可以使用 Contains 方法获取。
var SE = Shop.Sections.Where( s => obj.SectionObjects
.Select( so => so.SectionId )
.Contains( s.SectionId ))
.ToList();
翻译成
select * from Sections where sectionId in (...)
in 子句的值来自本地对象集合中的 id 列表。
【讨论】:
这并不完全正确。如果本地源先行,则可以使用连接。请参阅下面的答案。【参考方案2】:您不能将本地源加入 SQL 源, 但你可以将 SQL 源加入本地,v.v.
var SE = from c1 in obj.SectionObjects
join c in Shop.Sections on c1.SectionId equals c.SectionId
select c;
换句话说,本地资源必须放在第一位
【讨论】:
这应该是公认的答案。在这种方法中,(除非我大错特错),不会枚举 SQL 源(因此避免了一些 DB 开销) 如果 db 表相当小,此解决方案有效。但是,它确实枚举了从数据库到内存的整个表(通过 SQL 跟踪验证)来进行比较。我们有一个复杂的多表“SQL 源到本地”场景,因此开始出现内存不足异常错误。使用包含的其他答案允许查询使用“IN”在 SQL Server 上运行,并且只提取相关记录。这些答案应该是公认的答案,尤其是对于较大的表格。【参考方案3】:这应该在数据库端(使用IN
)而不是在内存中工作和完成:
var SE = from c in Shop.Sections
where obj.SectionObjects.Select(z => z.SectionId).Contains(c.SectionId)
select c;
L2S Profiler 对这类事情非常有帮助 - 您可以比较我的解决方案和其他解决方案生成的不同 SQL。
【讨论】:
这段代码无效,错误是:错误1 'System.Data.Linq.EntitySetvar SE = from c in Shop.Sections.AsEnumerable().ToList() 在 c.SectionId 上的 obj.SectionObjects.AsEnumerable().ToList() 中加入 c1 等于 c1.SectionId 选择 c;
dataGridView1.DataSource = SE;
【讨论】:
以上是关于本地序列不能在查询运算符的 LINQ to SQL 实现中使用,但 Contains() 运算符除外的主要内容,如果未能解决你的问题,请参考以下文章
为啥,当我在 WCF 服务中模拟时,当我尝试运行 LINQ to SQL 查询时,我的服务不能加载 System.Transactions?