【问题标题】:Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator本地序列不能在查询运算符的 LINQ to SQL 实现中使用,但 Contains() 运算符除外
【发布时间】: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; 行中遇到了这个错误
错误信息是:

本地序列不能在查询运算符的 LINQ to SQL 实现中使用,但 Contains() 运算符除外。

【问题讨论】:

  • 将鼠标悬停在 Shop.Sections 上并告诉我们它的类型。然后将鼠标悬停在 obj.SectionObjects 上并告诉我们它的类型。

标签: c# sql linq


【解决方案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.EntitySet.Contains(Shop.SectionObject)'的最佳重载方法匹配有一些无效参数
  • 是的,看起来 L2S 基本上已经死了 - nuget.org/packages/LinqToSqlProfiler
  • 在数据库端比在内存中快得多!
【解决方案4】:

var SE = from c in Shop.Sections.AsEnumerable().ToList() 在 c.SectionId 上的 obj.SectionObjects.AsEnumerable().ToList() 中加入 c1 等于 c1.SectionId 选择 c;

dataGridView1.DataSource = SE;

【讨论】:

    猜你喜欢
    • 2012-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多