Linq 查询排除相关实体为空

Posted

技术标签:

【中文标题】Linq 查询排除相关实体为空【英文标题】:Linq query to exclude related entities that are empty 【发布时间】:2020-09-26 10:43:18 【问题描述】:

在我当前的项目中,我想显示与 ICollections 相关的条目列表。 Plant 与 BadNeighbours 和 GoodNeighbours 都具有多对多关系。我使用的 Linq 语句是:

ICollection<Plant> plants = _context.Plants
                .Include(p => p.BadNeighbours)
                .Include(p => p.GoodNeighbours)
                .ToList();

这将显示植物表中的所有条目以及相关植物。但是,我想从列表中排除既没有 GoodNeighbours 也没有 BadNeighbours 的植物。

这些是实体: 植物

public class Plant


    public int Id  get; set; 
    public string Name  get; set; 

    public virtual ICollection<GoodPlants> GoodNeighbours  get; set; 
    public virtual ICollection<BadPlants> BadNeighbours  get; set; 

坏邻居

public class BadPlants

    public int PlantId  get; set; 
    public int BadNeighbourId  get; set; 

    public virtual Plant Plant  get; set; 
    public virtual Plant BadNeighbour  get; set; 

好邻居

public class GoodPlants

    public int PlantId  get; set; 
    public int GoodNeighbourId  get; set; 

    public virtual Plant Plant  get; set; 
    public virtual Plant GoodNeighbour get; set;

实体生成器

protected override void OnModelCreating(ModelBuilder modelBuilder)

   base.OnModelCreating(modelBuilder);
   modelBuilder.Entity<Plant>().HasKey(p => p.Id);
   modelBuilder.Entity<BadPlants>()
    .HasKey(u => new  u.BadNeighbourId, u.PlantId );

   modelBuilder.Entity<GoodPlants>()
    .HasKey(u => new  u.GoodNeighbourId, u.PlantId );

   modelBuilder.Entity<Plant>()
    .HasMany(p => p.GoodNeighbours)
    .WithOne(g => g.Plant)
    .HasForeignKey(g => g.PlantId)
    .OnDelete(DeleteBehavior.NoAction);

   modelBuilder.Entity<Plant>()
   .HasMany(p => p.BadNeighbours)
   .WithOne(b => b.Plant)
   .HasForeignKey(b => b.PlantId)
   .OnDelete(DeleteBehavior.NoAction);            

我尝试在最后一个include 语句之后添加Where(p =&gt; p.GoodNeighbours.Count() &gt; 0 &amp;&amp; p.BadNeighbours.Count() &gt; 0),虽然这会导致我的ICollection plants 中的植物数量正确,但关系GoodNeighbours 和BadNeighbours 不再包括在内。

我可以使用什么 Linq 语句来实现我的目的? 谢谢

【问题讨论】:

你能发布植物模型和依赖模型吗? 查看我上面编辑过的帖子 这篇文章可能会回答您的问题how-to-load-the-navigation-property-with-ef-core 我收到错误消息,即 lambda 表达式不是 Include 语句中的有效表达式。我试过了:.Include(p =&gt; p.BadNeighbours.Where(bn =&gt; bn.PlantId == p.Id || bn.BadNeighbourId == p.Id)) 您应该显示整个查询,而不仅仅是Where。也许你有一个 Select 让 EF 忽略 Includes 【参考方案1】:

也许会成功

ICollection<Plant> plants = _context.Plants
   .Where(p => !_context.BadPlants.Any(nb => nb.PlantId == p.Id || nb.BadNeighbourId == p.Id))
   .Where(p => !_context.GoodPlants.Any(nb => nb.PlantId == p.Id || nb.GoodNeighbourId == p.Id))
   .ToList();

【讨论】:

不幸的是,这也给了我完整的列表,包括没有关系的植物。 更新答案。 仍然没有加载相关的导航属性。我无法访问集合中相关植物的名称。 你的意思是_context.Plants.Select(pr =&gt; pr.Name)返回空值列表吗?

以上是关于Linq 查询排除相关实体为空的主要内容,如果未能解决你的问题,请参考以下文章

Linq:如果参数为空,如何排除条件

在 linq 查询后检查实体是不是为空

在 EFCore 急切加载 LINQ 查询中,如何在 ThenInclude() 表达式中引用***实体?

LINQ to Entities 无法识别该方法(在相关实体上)

3-实体数据模型与LINQ-分组

Linq 查询运行缓慢,但查询单独运行很快