Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core OwnsOne fails when saving

I have the following model:

public class User
{
    public Guid Id {get;set;}
    public string Username {get;set;}
    public string Address Useraddress {get;set;}
}

public class Address
{
    public string Street {get;set;}
    public string Zipcode {get;set;}
}

I want to save the data in Useraddress to the same User table. So I added an OwnsOne configuration to the context builder.

class UserEntityTypeConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.HasKey(x => x.Id);
        builder.OwnsOne(x => x.UserAddress);
    }
}

When I run the migrations tool then it all seems to be fine. This is the relevant part from the migrations script that is generated:

migrationBuilder.CreateTable(
    name: "Users",
    columns: table => new
    {
        Id = table.Column<Guid>(nullable: false),
        Username = table.Column<string>(nullable: false),
        Useraddress_Street = table.Column<string>(nullable: true),
        Useraddress_Zipcode = table.Column<string>(nullable: true)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Users", x => x.Id);
    });

Then when I later on try to add a User:

await _dbContext.Users.AddAsync(user);
await _dbContext.SaveChangesAsync();

I then get the following error:

The entity of 'User' is sharing the table 'Users' with 'User.Useraddress#Address', but there is no entity of this type with the same key value that has been marked as 'Added'

Is there something that I'm doing wrong?

PS. I'm using Entity Framework Core 2.0.

like image 373
Vivendi Avatar asked Mar 19 '18 19:03

Vivendi


1 Answers

EF Core 2.0 by default creates a primary key as a shadow property for the owned entity since it supports table splitting, therefore, the value of the UserAddress property in the User instance cannot be null and must be defined.

var user = new User
{
    Id = Guid.NewGuid(),
    Username = "...",
    UserAddress = new Address
    {
        Street = "...",
        Zipcode = "..."
    }
};

await _dbContext.Users.AddAsync(user);
await _dbContext.SaveChangesAsync();

If you want the values of the owned entity to be nulls then just define a default instance, i.e.:

var user = new User
{
    Id = Guid.NewGuid(),
    Username = "...",
    UserAddress = new Address()
};

You can read more about owned entity implicit keys here: https://learn.microsoft.com/en-us/ef/core/modeling/owned-entities#implicit-keys

like image 179
Alaa Masoud Avatar answered Nov 05 '22 07:11

Alaa Masoud