EF Core 如何向 .ThenIncludes 添加过滤器
Posted
技术标签:
【中文标题】EF Core 如何向 .ThenIncludes 添加过滤器【英文标题】:EF Core how to add a filter to .ThenIncludes 【发布时间】:2021-03-17 20:13:20 【问题描述】:我使用的是 EF Core 5.0.4
我有这三个有关系的实体。
public class Parent
[Key]
public int ParentId get; set;
[Key]
public short ChildId get; set;
public string ParentProp1 get; set;
public string ParentProp2 get; set;
public DateTime ProcessedDate get; set;
public DateTime Anniversary get; set;
public Child Child get; set;
public class Child
public Child()
Animals = new HashSet<Animals>();
[Key]
public short ChildId get; set;
public string ChildName get; set;
public virtual ICollection<Animals> Animals get; set;
//UPDATED TO INCLUDE PARENT
public Parent Parent get;set;
public class Animals
[Key]
public short AnimalId get; set;
[ForeignKey("ChildId")]
public short ChildId get; set;
public DateTime StartDate get; set;
public DateTime EndDate get; set;
public DateTime MAnniversary get; set;
public DateTime PAnniversary get; set;
public virtual Child Child get; set;
在我的存储库中,我试图返回父列表。如何在 IQueryable() 上添加过滤器..查看注释代码行...?
public List<Parent> Get(Request request)
var data = _context.Parents
.Include(r => r.Child)
.ThenInclude(a => a.Animals)
.AsQueryable().AsNoTracking();
data = data.Where(x => x.ProcessedDate == request.ProcessedDate);
// Here is the filter I'm trying to add but can't because data is an IQueryable() :
// Animals needs to be filtered based off a query like:
// data.Child.Animals = data.Child.Animals.Where( d => d.StartDate <= data.ProcessedDate && (
// d.EndDate == null || data.ProcessDate <= d.EndDate
// )
// && d.ChildId == data.ChildId && data.Anniversary >= d.MAnniversary
// ).ToList();
return data;
当只返回 Parent 时,我可以像下面这样添加过滤器查询而不会出现任何问题,因为 'data' 不是 IQueryable() :
public Parent Get(int id)
var data = _context.Parents
.Include(r => r.Child)
.ThenInclude(a => a.Animals)
.FirstOrDefault(x => x.ParentId == id);
data = data.Where(x => x.ProcessedDate == request.ProcessedDate);
data.Child.Animals = data.Child.Animals.Where(d => d.StartDate <= data.ProcessedDate && (
d.EndDate == null || data.ProcessDate <= d.EndDate
)
&& d.ChildId == data.ChildId && data.Anniversary >= d.MAnniversary
).ToList();
return data;
我尝试在 .ThenInlude() 上添加一个过滤器,如下所示,但它不起作用,因为我无法访问所需的属性。
var data = _context.Parents
.Include(r => r.Child)
.ThenInclude(a => a.Animals.Where(x => x.StartDate <= "this doesn't work because can't access Parent or Child properties")
.AsQueryable().AsNoTracking();
更新
我将导航父导航属性添加到子级,并将查询更改为基于内部关系。它看起来像这样:
var data = _context.Animals
.Include(r => r.Child)
.ThenInclude(a => a.Parent)
.Where(r => r.StartDate <= r.Child.Parent.ProcessedDate && (
r.EndDate == null || r.Child.Parent.ProcessDate <= r.EndDate
)
&& r.ChildId == r.Child.Parent.ChildId &&
r.Child.Parent.Anniversary >= r.MAnniversary
).AsQueryable().AsNoTracking();
【问题讨论】:
您使用的是 .net 5 吗?使用 EF Core 5?因为那是在 .net 5 中添加的,我相信 @MiltoxBeyond 我正在使用 EF Core 5.0.4 和 dotnet Core 3.1.0。 你想做什么?请描述您需要什么。 @zolty13 我想将“data.Child.Animals.Where(..)”过滤器添加到 AsQueryable()。 基于内部关系的查询呢?喜欢:_context.Children.Include(c => c.Animals.Where(a => /*condition*/ )) .include(c=>c.Parent).where(c=>c.Animals.Count()>0)
【参考方案1】:
我将 Parent 导航属性添加到 Child 并将查询更改为基于内部关系。它看起来像这样:
var data = _context.Animals
.Include(r => r.Child)
.ThenInclude(a => a.Parent)
.Where(r => r.StartDate <= r.Child.Parent.ProcessedDate && (
r.EndDate == null || r.Child.Parent.ProcessDate <= r.EndDate
)
&& r.ChildId == r.Child.Parent.ChildId &&
r.Child.Parent.Anniversary >= r.MAnniversary
).AsQueryable().AsNoTracking();
【讨论】:
以上是关于EF Core 如何向 .ThenIncludes 添加过滤器的主要内容,如果未能解决你的问题,请参考以下文章
向数据库添加新表后如何更新 Entity Framework Core