实体框架不将Where子句作为WHERE子句发送到SQL Server

Dan*_*ola 8 .net c# entity-framework where-clause

我有一个简单的数据库,有网站,每个网站都有一堆帖子.

我正在尝试获取某个站点的所有"公共"帖子(我有一个名为site的变量,已经是EF提供的一个实例)

第一个显而易见的事情是:

  var posts = from post in site.Posts
              where post.Public == true
              orderby post.PublicationTime descending
              select post;
Run Code Online (Sandbox Code Playgroud)

这给我带来了我想要的东西,但是在研究SQL Server Profiler时,WHERE只过滤Public字段,而不是Site.实际上,在SQL Server中运行Profiler捕获的查询确实会带回所有站点中的所有帖子(这显然是在ASP.Net方面稍后进行过滤).

然后我尝试了:

  var posts = from post in db.Posts
              where post.Site == site && post.Public == true
              orderby post.PublicationTime descending
              select post;
Run Code Online (Sandbox Code Playgroud)

结果相同.

我在这里做了一些根本愚蠢的事情吗?
实体框架是否总是在客户端进行过滤?

谢谢!
丹尼尔

Cra*_*ntz 9

您需要了解LINQ to Entities和LINQ to Objects之间的区别.在使用Entity Framework时跟踪这一点非常重要.

当您针对ObjectContext发出查询时,您正在使用LINQ to Entities.这将返回IQueryable.只要您使用IQueryable类型的变量,就可以使用LINQ API进一步组合查询,并且当您最终枚举结果时,它将转换为SQL.

但是你说:

(我有一个名为site的变量,它已经是EF带来的一个实例)

在这里,您要查询对象的属性,因此您正在使用LINQ to Objects,而不是LINQ to Entities.这意味着您的查询具有不同的提供程序,并且不会转换为SQL.

关于你的第二个问题:

var posts = from post in db.Posts
            where post.Site == site && post.Public == true
            orderby post.PublicationTime descending
            select post;
Run Code Online (Sandbox Code Playgroud)

EF不允许您对L2E中的实例进行身份比较.你必须比较密钥.尝试:

var posts = from post in db.Posts
            where post.Site.Id == site.Id && post.Public
            orderby post.PublicationTime descending
            select post;
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我换post.Public == truepost.Public.我认为它更干净.


小智 5

如果有人使用方法语法对此有疑问:

如果将a传递Func<TEntity,Boolean>给该.Where方法,则查询从数据库返回后将应用过滤器功能。这是因为方法的返回值.Where返回IEnumerable。另一方面,如果将传递Expression<Func<TEntity,Boolean>.Where方法,则过滤器函数会生成一个where子句,该子句将发送到数据库。这是因为.Where返回的是IQueryable。只要您坚持使用IQueryables,就可以构建要发送到数据库的查询。当您返回IEnumerable时,该方法之前的所有内容都将用于创建查询,而IEnumerable之后的所有内容都将应用于返回的内容。仅当将lambda函数存储在变量中时,这才真正重要。如果您将lambda直接传递到.Where方法,您通常没有问题。希望这可以帮助!!

IEnumerable其中:https : //msdn.microsoft.com/zh-cn/library/bb549418(v= vs.110).aspx

可查询的位置:https ://msdn.microsoft.com/zh-cn/library/bb535040( v= vs.110).aspx