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)
结果相同.
我在这里做了一些根本愚蠢的事情吗?
实体框架是否总是在客户端进行过滤?
谢谢!
丹尼尔
您需要了解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 == true了post.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