Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core HasMany vs OwnsMany

For one to many relationship, what's the difference between HasMany and OwnsMany? When should I use one over another?

For example:

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; }
}

The Entity Configuration:

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();
    }
}

The generated migration is below:

        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);
            });

if I update the xxxConfiguration by replacing the OwnsMany with HasMany, like:

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

The generated migration is below:

        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);
            });

As you can see, the migration generated by both are the same. So what's the point of OwnsMany?

like image 802
Charlie Avatar asked Oct 23 '19 06:10

Charlie


2 Answers

From documentation:

EF Core allows you to model entity types that can only ever appear on navigation properties of other entity types. These are called owned entity types. The entity containing an owned entity type is its owner.

Owned entities are essentially a part of the owner and cannot exist without it, they are conceptually similar to aggregates.

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

like image 185
Ljubomir Bacovic Avatar answered Nov 02 '22 22:11

Ljubomir Bacovic


One of the differences is that relationships configured with OwnsMany() will include the owned entities by default when querying the owner from the database, whilst when using WithMany() you have to specify AutoInclude() manually if you want them to be included every time you get the owner entity form the database.

Also from documentation: Querying owned types

like image 1
Mentoliptus Avatar answered Nov 02 '22 23:11

Mentoliptus