【问题标题】:Linq-to-SQL EntitySet Is Not IQueryable -- Any Workarounds?Linq-to-SQL EntitySet 不是 IQueryable - 任何解决方法?
【发布时间】:2011-07-07 23:56:24
【问题描述】:

当您在 Linq-to-SQL 中查询模型对象的 EntitySet 属性时,它会返回实体集中的所有行并在客户端执行任何进一步的查询。

这在网上的一些地方得到了证实,我自己也观察到了这种行为。 EntitySet 没有实现 IQueryable。

我所要做的就是转换如下代码:

var myChild = ... ;
// Where clause performed client-side.
var query = myChild.Parents().Where(...) ;  

到:

var myChild = ... ;
// Where clause performed in DB and only minimal set of rows returned.
var query = MyDataContext.Parents().Where(p => p.Child() == myChild) ;  

有人知道更好的解决方案吗?

第二个问题:实体框架中是否已解决此问题?

【问题讨论】:

  • 我不知道为什么我没有得到答案,尤其是来自微软的人。这似乎并不重要,但实际上它妨碍了首选的范围数据访问编码风格。例如,如果要将数据范围限制为当前用户拥有的对象,则可以使用:theUser.Products().Where(...) 而不是 DataContext.Products().Where(p => p .User() == theUser).Where(...)。使编码重复并且更有可能引入错误。与 Rails ActiveRecord 对比:guides.rubyonrails.org/association_basics.html#why-associations.

标签: linq-to-sql linq-to-entities


【解决方案1】:

EntitySet 只是实体的集合。它实现了 IEnumerable,而不是 IQueryable。 Active Record 模式指定实体直接负责自己的持久性。 OR 映射器实体对持久层没有任何直接的了解。 OR Mappers 将此职责与工作单元和身份映射职责一起放入数据上下文中。因此,如果您需要查询数据源,则必须使用上下文(或 Table 对象)。改变这一点会改变使用中的模式。

【讨论】:

  • 我明白了。不过,他们确实在一些早期的 linq-to-sql 测试版中启用了此功能。也许问题是我更喜欢另一种常用的模式!我发现无论如何我都需要删除大量的 l2s 并用老式的手写 SQL 和普通对象替换。
【解决方案2】:

我遇到了类似的问题:How can I make this SelectMany use a join。在使用 LINQPad 很长一段时间后,我找到了一个不错的解决方法。关键是将您正在查看的 EntitySetinside 推送到 SelectMany、Select、Where 等。一旦它进入内部,它就变成了一个 Expression,然后提供者可以将它变成一个适当的查询。 p>

用你的例子试试这个:

var query = from c in Children
            where c == myChild
            from p in c.Parents
            where p.Age > 35
            select p;

我无法 100% 验证此查询,因为我不知道您的模型的其余部分。但是查询的前两行导致它的其余部分变成一个表达式,提供者变成一个连接。这确实适用于我自己的示例,该示例与上面链接的问题有关。

【讨论】:

  • 谢谢!但我的主要目标是保留语法,使其自然地作用于仅由父级拥有的子级(在语句的后面没有单独的子句)。总的来说,我正在将越来越多的代码从 LinqToSQL 转移到纯 SQL,因为玩这些技巧以使高效的 SQL 出现在另一端非常耗时。
猜你喜欢
  • 2010-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多