【发布时间】:2019-03-01 07:33:17
【问题描述】:
我使用 EF Core 设置了一个自引用实体,如下所示:
实体
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; }
}
绑定
modelBuilder.Entity<DetailType>()
.ToTable("detailtype")
.HasOne(x => x.ParentType)
.WithMany(x => x.ChildTypes)
.HasForeignKey(x => x.ParentTypeId);
我正在通过 API 检索这些实体,当前结果如下所示:
[
{
"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
}
]
我遇到的问题是数组中的第三项与第二项正好相反。有没有办法避免这种情况,所以我只有父母 -> 孩子关系,而不是父母 -> 孩子以及孩子 -> 父母。上面的示例是我的 API 实际返回的内容的大幅缩减版本,因此我想尽可能减少不必要的膨胀,因为会发生很多关系。
理想情况下,我想要摆脱 ParentType 属性,但仍然拥有 ChildTypes 集合,但我不确定如何在模型构建器中定义它。
编辑:
我已经删除了流畅的关系,因为它不需要。我还尝试了以下方法:
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 顺便说一下 DbSet)
但是,这需要将 ChildTypes 更改为 IQueryable,当我这样做时,我得到以下异常:
实体类型上的导航属性“ChildTypes”的类型 'DetailType' 是 'EntityQueryable' 未实现 收藏。集合导航属性必须 实现目标类型的ICollection。
【问题讨论】:
-
如何为您的 api 使用不包含 ParentType 属性的单独模型。然后使用例如简单地将内部(db)模型映射到控制器中的外部(api)模型。自动映射器automapper.org
-
如前所述,有一些设计级别的正确方法可以做到这一点。但作为一种解决方法 - 您可以申请
.Where(x => x.parentTypeId == null)以摆脱除顶级之外的所有项目。这应该提供所需的输出。 -
是的,您需要使用视图模型/DTO 来处理此问题,而不是直接使用实体类。
-
@YeldarKurmangaliyev 这确实只返回根项目。但是,它也会删除
ChildTypes中的所有项目,所以我得到的只是根项目,这不是我想要的。 -
@AndyFurniss 它确实返回了包含
ChildItems中列出的所有非根项目的根项目,不是吗?为什么会删除ChildTypes中的所有项目?
标签: c# entity-framework asp.net-core entity-framework-core self-referencing-table