問題

私は2つのエンティティを持っています:

 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テーブルにあります。私は、parent-child階層の最上位の親であった子供(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