问题

我有两个实体:

 public class Child
{
    [Key]
    public string Id { get; set; }
    public List<Parent> Parents { get; set; }
}

public class Parent
{
    [Key]
    public string Id { get; set; } // If the parent is in Child, the that Id, otherwise a random Guid.
    public string ParentId { get; set; }  // Id of the parent of this parent.
    public string ChildId { get; set; }   // Id of the child from the Child class.
    public Child Child { get; set; }
}
 

Db上下文设置如下:

 public class MyContext : DbContext
{
   public MyContext(DbContextOptions<MyContext> options) : base(options)
   {
   }

   protected override void OnModelCreating(ModelBuilder builder)
   {
       builder.Entity<Child>();
       builder.Entity<Parent>().HasKey(k => new {k.Id, k.ChildId});
       builder.Entity<Parent>()
              .HasOne(h => h.Child)
              .WithMany(w => w.Parents)
              .IsRequired()
              .OnDelete(DeleteBehavior.Cascade);
   }
}
 

实际数据是这样的,并非每个父母都在Child表中,但每个孩子都在Child表中.我想查询孩子(从Child表),他们恰好是parent-child层次结构中最顶级的父级.例如:

         /*
         * Tree:
         *     p1(P)--------p2 (P)------r2 (P&C)
         *      |-----------|           |
         *      |                       c3 (P&C)
         *      |                       |
         *      |                      gc1 (C)
         *     r1 (P&C)---|
         *      |         |
         *     c1 (C)     c2 (C)
         */
 

这个树应该产生r1r2作为解决方案,因为它们位于树的顶部和子表中.换句话说,它们没有父母也是孩子.

我到目前为止的尝试是:

 using(var ctx = new MyContext(options))
{
    var q = ctx.Set<Child>();
    var mainQ = q.GroupJoin(q.Where(w => w.Parents.Any()),
                            o => o.Id,
                            i => i.Parents.First().ParentId /* For now I'm just trying to handle a single parent.*/,
                           (o, i) => new { o, i })
                 .Where(w => !w.i.Any())
                 .Select(s => s.o)
                 .Union(q.Where(w => !w.Parents.Any()));
}
 

但是,此查询给了我错误:

 ArgumentException: The input sequence must have items of type Child but it has items of type Microsoft.EntityFrameworkCore.Query.Internal.AnonymousObject
 

感谢任何援助。

  最佳答案

我刚刚设法弄清楚:)

 var childIds = ctx.Set<Child>().Select(s => s.Id);

var query = ctx.Set<Child>()
    .GroupJoin(ctx.Set<Parent>(), o => o.Id, i => i.Id, (o, i) => new {o, i})
    .Where(w => w.i.Any())
    .Select(s => s.o)
    .Include(i => i.Parents)
    .Where(w => !w.Parents.Select(s => s.Id).Intersect(childIds).Any());
 

想法是找到所有父母的孩子(GroupJoin,然后是Where子句),然后检查这些孩子的父母是否在孩子桌上。

如果有人有更好/更高性能的解决方案,请发布答案.

  相同标签的其他问题

c#linqef-core-2.1