c# - EF Core one-way self referencing entity binding
问题描述
I have set up a self referential entity using EF Core which looks like this:
Entity
public class DetailType
{
public int DetailTypeId { get; set; }
public string Name { get; set; }
public int? ParentTypeId { get; set; }
public DetailType ParentType { get; set; }
public IEnumerable<DetailType> ChildTypes { get; set; }
}
Binding
modelBuilder.Entity<DetailType>()
.ToTable("detailtype")
.HasOne(x => x.ParentType)
.WithMany(x => x.ChildTypes)
.HasForeignKey(x => x.ParentTypeId);
I am retrieving these entities via an API and the current result looks something like this:
[
{
"detailTypeId": 20,
"name": "Money",
"parentTypeId": null,
"parentType": null,
"childTypes": null
},
{
"detailTypeId": 22,
"name": "Optional Extra",
"parentTypeId": null,
"parentType": null,
"childTypes": [
{
"detailTypeId": 42,
"name": "Extra Nights",
"parentTypeId": 22,
"childTypes": null
}
]
},
{
"detailTypeId": 42,
"name": "Extra Nights",
"parentTypeId": 22,
"parentType": {
"detailTypeId": 22,
"name": "Optional Extra",
"parentTypeId": null,
"parentType": null,
"childTypes": []
},
"childTypes": null
}
]
The problem I have with this is that the third item in the array is just the reverse of the second. Is there a way to avoid this so that I only have the parent -> child relationship rather than both parent -> child as well as child -> parent. The example above is a heavily cut-down version of what my API is actually returning so I want to reduce the unnecessary bloat as much as possible because there'll be a lot of relationships going on.
Ideally what I want is to just get rid of the ParentType property but still have the ChildTypes collection but I'm not sure how to define that in the model builder.
EDIT:
I have removed the fluent relationship as it's not needed. I've also tried the following:
var roots = this.Items.Where(x => x.ParentTypeId == null);
foreach (var root in roots)
{
root.ChildTypes = this.Items.Where(x => x.ParentTypeId == root.DetailTypeId);
}
return roots.ToList();
(this.Items
is the DbSet by the way)
However this requires changing ChildTypes
to an IQueryable
and when I do that I get the following exception:
The type of navigation property 'ChildTypes' on the entity type 'DetailType' is 'EntityQueryable' which does not implement ICollection. Collection navigation properties must implement ICollection<> of the target type.
解决方案
首先要做的事情 - 您不需要在模型构建器中指定此关系。它自己计算出来。
然后关于您的问题-我想到的第一件事(我不知道您的整个数据集)是获取所有DetailType
具有ParentTypeId == null
.
这样,您将获得根,然后递归地构建tree
子元素。
这样做会清理你的结果,你会看到你想看到的结构。
推荐阅读
- c# - 为什么工具条按钮不会读取复选框状态?
- java - 有没有人有一个使用 Cucumber/Gherkin 和 Allure Reports for Java/Groovy-based Gradle 项目的示例存储库?
- linux - 如何在bash中格式化文本文件中的变量?
- javascript - 如何从另一个类创建一个对象,并将其推入状态数组?
- java - 我需要帮助将我的代码从 c++ 转换为 java
- jenkins - 如何获取管道中使用的共享库列表?
- python - return 语句之前的打印语句给出正确的值,但函数返回 Nonetype
- python - Pandas 在其他列中创建给定最小值和最大值的 Numpy 数组列
- javascript - 是否有一个使用 RxJS 的 Writable Stream 的功能更强大的实现,它在处理之前等待一个 Promise 解决?
- python - 如何将字典值与数组值匹配并仅输出一个