EF Core HasMany 与 OwnsMany

Cha*_*lie 20 entity-framework ef-core-2.2

对于一对多关系,HasManyOwnsMany 有什么区别?我什么时候应该使用一个?

例如:

public class xxx 
{
    public virtual IReadOnlyCollection<xxxHistoryEntity> Histories => _histories;
    private readonly List<xxxHistoryEntity> _histories = new List<xxxHistoryEntity>();
}

public class xxxHistoryEntity : Entity<string>
{
    public string State { get; set; }
    public string NodeId { get; set; }
    public string Message { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

实体配置:

class xxxConfiguration
    : IEntityTypeConfiguration<xxx>
{
    public void Configure(EntityTypeBuilder<xxx> builder)
    {
        builder.OwnsMany(itm => itm.Histories, collbuilder =>
        {
            collbuilder.HasForeignKey("xxxid");
        });
    }
}

class xxxHistoryConfiguration
    : IEntityTypeConfiguration<xxxHistoryEntity>
{
    public void Configure(EntityTypeBuilder<xxxHistoryEntity> builder)
    {
        builder.ToTable("xxx_histories");
        builder.HasKey(itm => itm.Id);
        builder.Property(itm => itm.Id)
             .ValueGeneratedOnAdd();
    }
}
Run Code Online (Sandbox Code Playgroud)

生成的迁移如下:

        migrationBuilder.CreateTable(
            name: "xxx_histories",
            columns: table => new
            {
                id = table.Column<string>(nullable: false),
                xxxid = table.Column<string>(nullable: false),                    
                state = table.Column<string>(nullable: true),
                nodeid = table.Column<string>(nullable: true),
                message = table.Column<string>(nullable: true),
                xmin = table.Column<uint>(type: "xid", nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_xxx_histories", x => new { x.id, x.xxxid });
                table.ForeignKey(
                    name: "fk_xxxhistoryentity_xxx_xxxarid",
                    column: x => x.xxxid,
                    principalTable: "xxx",
                    principalColumn: "id",
                    onDelete: ReferentialAction.Cascade);
            });
Run Code Online (Sandbox Code Playgroud)

如果我通过用 HasMany 替换OwnsMany来更新xxxConfiguration,例如:

class xxxConfiguration
    : IEntityTypeConfiguration<xxx>
{
    public void Configure(EntityTypeBuilder<xxx> builder)
    {
        builder.HasMany(itm => itm.Histories)
            .WithOne()
            .HasForeignKey("xxxid");
    }
}
Run Code Online (Sandbox Code Playgroud)

生成的迁移如下:

        migrationBuilder.CreateTable(
            name: "xxx_histories",
            columns: table => new
            {
                id = table.Column<string>(nullable: false),
                xxxid = table.Column<string>(nullable: false),
                state = table.Column<string>(nullable: true),
                nodeid = table.Column<string>(nullable: true),
                message = table.Column<string>(nullable: true),
                xmin = table.Column<uint>(type: "xid", nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_xxx_histories", x => new { x.id, x.xxxid });
                table.ForeignKey(
                    name: "fk_xxxhistoryentity_xxx_xxxid",
                    column: x => x.xxxid,
                    principalTable: "xxx",
                    principalColumn: "id",
                    onDelete: ReferentialAction.Cascade);
            });
Run Code Online (Sandbox Code Playgroud)

如您所见,两者生成的迁移是相同的。那么,OwnsMany 的意义何在?

Lju*_*vic 17

来自文档:

EF Core 允许您对只能出现在其他实体类型的导航属性上的实体类型进行建模。这些称为拥有的实体类型。包含自有实体类型的实体是其所有者。

拥有的实体本质上是所有者的一部分,没有所有者就无法存在,它们在概念上类似于聚合。

https://learn.microsoft.com/en-us/ef/core/modeling/owned-entities

  • @Charlie在[文档](https://learn.microsoft.com/en-us/ef/core/modeling/owned-entities#by-design-restrictions)中现在显示:_You can not create a DbSet&lt;T&gt;对于拥有的类型。您无法使用 ModelBuilder_ 上的自有类型调用 Entity&lt;T&gt;() (6认同)
  • 我之前确实读过该文档,我知道它是针对聚合或值对象之类的概念,但我仍然不明白当我使用“OwnsMany”时有什么明显的区别。有什么我不能只使用 HasMany 做的事情吗? (5认同)
  • 如果您使用 OwnsMany,您将只能将此类的对象作为另一个类的导航属性进行访问。 (5认同)
  • 更多阅读:Owns API 通常代表 [DDD Aggregation](https://www.martinfowler.com/bliki/DDD_Aggregate.html) 或 [UML Composition](https://www.uml-diagrams.org/composition.html) ) (4认同)

Men*_*tus 6

区别之一是,OwnsMany()当从数据库查询所有者时,配置的关系将默认包含拥有的实体,而使用时,WithMany()您必须AutoInclude()手动指定是否希望每次从数据库获取所有者实体时都包含它们。

也来自文档:查询拥有的类型