Jas*_*ord 29 entity-framework-core
我正在尝试过滤初始查询.我已经嵌套了包含模型的叶子.我正在尝试根据其中一个包含的属性进行过滤.例如:
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList();
}
Run Code Online (Sandbox Code Playgroud)
我怎么能说呢.Where(w => w.post.Author == "me")?
Ger*_*old 103
Entity Framework core 5 是第一个支持过滤的IncludeEF 版本。
支持的操作:
WhereOrderBy(Descending)/ThenBy(Descending)SkipTake每个导航只允许一个过滤器,因此对于需要多次包含相同导航的情况(例如,在同一个导航上包含多个 ThenInclude)仅应用一次过滤器,或为该导航应用完全相同的过滤器。
context.Customers
.Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.OrderDetails)
.Include(c => c.Orders).ThenInclude(o => o.Customer)
Run Code Online (Sandbox Code Playgroud)
或者
context.Customers
.Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.OrderDetails)
.Include(c => c.Orders.Where(o => o.Name != "Foo")).ThenInclude(o => o.Customer)
Run Code Online (Sandbox Code Playgroud)
另一个重要说明:
使用新过滤器操作包含的集合被视为已加载。
这意味着如果启用了延迟加载,Orders则从上一个示例中解决一个客户的集合将不会触发整个Orders集合的重新加载。
此外,Include同一上下文中的两个后续过滤的s 将累积结果。例如...
context.Customers.Include(c => c.Orders.Where(o => !o.IsDeleted))
Run Code Online (Sandbox Code Playgroud)
...其次是...
context.Customers.Include(c => c.Orders.Where(o => o.IsDeleted))
Run Code Online (Sandbox Code Playgroud)
......将导致customers与Orders包含所有订单的集合。
如果其他Orders 被加载到相同的上下文中,customers.Orders由于关系 fixup,更多的可能会被添加到集合中。这是不可避免的,因为 EF 的变更跟踪器是如何工作的。
context.Customers.Include(c => c.Orders.Where(o => !o.IsDeleted))
Run Code Online (Sandbox Code Playgroud)
...其次是...
context.Orders.Where(o => o.IsDeleted).Load();
Run Code Online (Sandbox Code Playgroud)
...将再次导致customers与Orders包含所有订单的集合。
过滤器表达式应包含可用作集合的独立谓词的谓词。一个例子将说明这一点。假设我们想要包含由以下属性过滤的订单Customer:
context.Customers.Include(c => c.Orders.Where(o => o.Classification == c.Classification))
Run Code Online (Sandbox Code Playgroud)
它编译,但它会抛出一个非常技术性的运行时异常,基本上是说o.Classification == c.Classification因为c.Classification找不到而无法翻译。必须使用从Orderto的反向引用重写查询Customer:
context.Customers.Include(c => c.Orders.Where(o => o.Classification == o.Customer.Classification))
Run Code Online (Sandbox Code Playgroud)
谓词o => o.Classification == o.Customer.Classification)是“独立的”,因为它可以用于Orders独立过滤:
context.Orders.Where(o => o.Classification == o.Customer.Classification) // No one would try 'c.Classification' here
Run Code Online (Sandbox Code Playgroud)
此限制可能会在比当前稳定版本(EF 核心 5.0.7)更高的 EF 版本中更改。
由于Where是一个扩展方法,IEnumerable很明显只能过滤集合。无法过滤参考导航属性。如果我们想获得订单并且只Customer在客户活跃时填充他们的属性,我们不能使用Include:
context.Orders.Include(c => c.Customer.Where( ... // obviously doesn't compile
Run Code Online (Sandbox Code Playgroud)
FilteredInclude在如何影响整个查询的过滤方面引起了一些混淆。经验法则是:不会。
该声明...
context.Customers.Include(c => c.Orders.Where(o => !o.IsDeleted))
Run Code Online (Sandbox Code Playgroud)
...从上下文中返回所有客户,而不仅仅是订单未删除的客户。中的过滤器Include不会影响主查询返回的项目数。
另一方面,声明...
context.Customers
.Where(c => c.Orders.Any(o => !o.IsDeleted))
.Include(c => c.Orders)
Run Code Online (Sandbox Code Playgroud)
...只返回至少有一个未删除的订单但所有订单都在Orders集合中的客户。主查询的过滤器不会影响由 返回的每个客户的订单Include。
要获取未删除订单的客户并仅加载他们未删除的订单,需要两个过滤器:
context.Customers
.Where(c => c.Orders.Any(o => !o.IsDeleted))
.Include(c => c.Orders.Where(o => !o.IsDeleted))
Run Code Online (Sandbox Code Playgroud)
另一个令人困惑的领域是过滤Include和投影 ( select new { ... }) 之间的关系。简单的规则是:投影忽略Includes,过滤与否。像这样的查询...
context.Customers
.Include(c => c.Orders)
.Select(c => new { c.Name, c.RegistrationDate })
Run Code Online (Sandbox Code Playgroud)
...将在没有连接的情况下生成 SQL Orders。至于EF,它和...
context.Customers
.Select(c => new { c.Name, c.RegistrationDate })
Run Code Online (Sandbox Code Playgroud)
Include过滤后会令人困惑,但Orders也用于投影:
context.Customers
.Include(c => c.Orders.Where(o => !o.IsDeleted))
.Select(c => new
{
c.Name,
c.RegistrationDate,
OrderDates = c.Orders.Select(o => o.DateSent)
})
Run Code Online (Sandbox Code Playgroud)
人们可能期望OrderDates只包含来自未删除订单的日期,但它们包含来自所有Orders. 同样,投影完全忽略了Include. 投影和Include是分开的世界。
这个问题有趣地证明了他们过着自己的生活是多么严格:
context.Customers
.Include(c => c.Orders.Where(o => !o.IsDeleted))
.Select(c => new
{
Customer = c,
OrderDates = c.Orders.Select(o => o.DateSent)
})
Run Code Online (Sandbox Code Playgroud)
现在暂停片刻并预测结果......
不那么简单的规则是:预测并不总是忽略Include。当存在于所述突起的实体Include可以被应用,它是施加。这意味着Customer在投影中包含其 undeleted Orders,而OrderDates仍包含所有日期。你做对了吗?
ale*_*sio 21
不可行.
有关此主题的讨论正在进行中:https: //github.com/aspnet/EntityFramework/issues/1833
我建议查看那里列出的任何第三方库,例如:https://github.com/jbogard/EntityFramework.Filters
Fra*_*ans 14
您也可以撤消搜索.
{
var blogs = context.Author
.Include(author => author.posts)
.ThenInclude(posts => posts.blogs)
.Where(author => author == "me")
.Select(author => author.posts.blogs)
.ToList();
}
Run Code Online (Sandbox Code Playgroud)
Ros*_*oss 10
不确定 Include() AND ThenInclude(),但使用单个 include 很容易做到这一点:
var filteredArticles =
context.NewsArticles.Include(x => x.NewsArticleRevisions)
.Where(article => article.NewsArticleRevisions
.Any(revision => revision.Title.Contains(filter)));
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
尽管(仍在讨论中)使用 EF Core 不可行,但我已经设法通过 EF Core DbSet 使用 Linq to Entities 来实现。在您的情况下,而不是:
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList()
Run Code Online (Sandbox Code Playgroud)
.. 你将拥有:
await (from blog in this.DbContext.Blogs
from bPost in blog.Posts
from bpAuthor in bPost.Author
where bpAuthor = "me"
select blog)
.ToListAsync();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23854 次 |
| 最近记录: |