在 EF Core 中应用投影时处理对象引用的正确方法是什么?

What is the proper way of handling object reference when applying projections in EF Core?

给定以下对象的简单示例:

public class Item 
{
    public int Id { get; set; }

    public string Description { get; set; }

    public Item ChildItem { get; set; }
}

假设:

builder.HasOne(x => x.ChildItem)
    .WithMany()
    .IsRequired(false)
    .OnDelete(DeleteBehavior.Restrict);
public class ItemProjection 
{
    public int Id { get; set; }

    public ItemProjection ChildItem { get; set; }
}

我正在尝试找出是否有 正确 方法将实体作为投影返回。

我想到的选项是:

请注意,在某些情况下,返回的集合将包含包含子项的父项和单独的子项作为没有子项的父项。在这种情况下,第一个选项也是 returns 单独的实例,尽管至少在我看来,它们应该是同一个实例。

在应用程序生命周期的后期,这些投影将被修改并转换回实体。

主要问题是 - 是否有处理此类事情的首选/正确方法?

投影背后的想法是为消费者提供消费者需要的东西,而不是数据可以提供的一切。由于投影通常用于 server/service 和 consumer/client 之间的传输层,这通常涉及序列化之类的事情,在这种情况下,担心单个实例与多个实例会变成 non-concern。最终消费者几乎总是会接收多个实例,并在将数据发送回服务器时返回多个实例。

理想情况下,预测应该将数据限制在消费者需要看到的范围内,这可能意味着如果维护数据关系没有真正的好处,则需要扁平化数据关系。这也可能意味着虽然您的域模型可能被规范化为 Item Item -> Item Child,但您预计的“child”不需要公开其底层“Item”具有的所有内容,(包括它自己可能的 child) 在这种情况下你可以考虑:

ItemProjection
{
   Id,
    // ... Item Fields
   ChildId,
   ChildField
   // ...
}

ItemProjection
{
    Id,
    // ... Item Fields
    ChildProjection Child
}

其中 ChildProjection 是一个单独的定义,特定于表示此关系中的 child 所需的数据。 (不一定是所有“项目”字段)

大多数情况下,对于 1..1 / 0..1 关系,我选择展平投影,因为 child(ren) 中我关心的字段数量相对较少。对于我确实需要 child 的更多细节的情况,我将使用 child 投影。在我的消费者特别想要构建一个 self-referencing 树的情况下,我只会考虑类似 ItemProjection Child 的东西。