Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用LINQ with EF Core在树状层次结构中查找第一个父级_C#_Linq_Tree_Ef Core 2.1 - Fatal编程技术网

C# 如何使用LINQ with EF Core在树状层次结构中查找第一个父级

C# 如何使用LINQ with EF Core在树状层次结构中查找第一个父级,c#,linq,tree,ef-core-2.1,C#,Linq,Tree,Ef Core 2.1,我有两个实体: 公共类子类 { [关键] 公共字符串Id{get;set;} 公共列表父项{get;set;} } 公共类父类 { [关键] 公共字符串Id{get;set;}//如果父项在子项中,则该Id为,否则为随机Guid。 公共字符串ParentId{get;set;}//此父级的父级Id。 公共字符串ChildId{get;set;}//child类中子类的Id。 公共子项{get;set;} } Db上下文的设置如下所示: 公共类MyContext:DbContext { 公共My

我有两个实体:

公共类子类
{
[关键]
公共字符串Id{get;set;}
公共列表父项{get;set;}
}
公共类父类
{
[关键]
公共字符串Id{get;set;}//如果父项在子项中,则该Id为,否则为随机Guid。
公共字符串ParentId{get;set;}//此父级的父级Id。
公共字符串ChildId{get;set;}//child类中子类的Id。
公共子项{get;set;}
}
Db上下文的设置如下所示:

公共类MyContext:DbContext
{
公共MyContext(DbContextOptions):基本(选项)
{
}
模型创建时受保护的覆盖无效(ModelBuilder)
{
builder.Entity();
builder.Entity().HasKey(k=>new{k.Id,k.ChildId});
builder.Entity()
.HasOne(h=>h.Child)
.有许多(w=>w.父母)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
}
实际数据是这样的,不是每个父项都在
子项
表中,而是每个子项都在
子项
表中。我想查询(从
Child
表中)恰好是父子层次结构中最顶层的父对象的子对象。例如:

        /*
         * Tree:
         *     p1(P)--------p2 (P)------r2 (P&C)
         *      |-----------|           |
         *      |                       c3 (P&C)
         *      |                       |
         *      |                      gc1 (C)
         *     r1 (P&C)---|
         *      |         |
         *     c1 (C)     c2 (C)
         */
此树应该为解决方案生成
r1
r2
,因为它们位于树的顶部以及子表中。换句话说,他们没有一个父母也是孩子

到目前为止,我的努力是:

使用(var ctx=new MyContext(选项))
{
var q=ctx.Set();
var mainQ=q.GroupJoin(q.Where(w=>w.Parents.Any()),
o=>o.Id,
i=>i.Parents.First().ParentId/*目前,我只想处理单亲。*/,,
(o,i)=>新的{o,i})
.Where(w=>!w.i.Any())
.选择(s=>s.o)
.Union(q.Where(w=>!w.Parents.Any());
}
但是,此查询给了我一个错误:

ArgumentException:输入序列必须具有Child类型的项,但具有Microsoft.EntityFrameworkCore.Query.Internal.AnonymousObject类型的项


非常感谢您的帮助。

我刚刚设法弄明白:)

var childIds=ctx.Set().Select(s=>s.Id);
var query=ctx.Set()
.GroupJoin(ctx.Set(),o=>o.Id,i=>i.Id,(o,i)=>new{o,i})
.Where(w=>w.i.Any())
.选择(s=>s.o)
.包括(i=>i.父母)
.Where(w=>!w.Parents.Select(s=>s.Id).Intersect(childid.Any());
这个想法是找到所有作为父母的孩子(
GroupJoin
后跟
Where
子句),然后检查这些孩子的父母是否在children表中


如果有人有更好/更高性能的解决方案,请给出答案。

为什么要求同时有父类和子类?一个
节点
类难道还不够吗?有
公共节点父节点
公共节点子节点
?@Stucky由于超出此问题范围的原因,无法执行此操作。我需要单独存储它们。所以这些类不能以任何方式更改吗?@Stucky不,对不起:D
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());