EF Core OwnsOne 在保存时失败

EF Core OwnsOne fails when saving

我有以下型号:

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

我想把Useraddress中的数据保存到同一个Usertable中。所以我向上下文构建器添加了一个 OwnsOne 配置。

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

当我 运行 迁移工具时,一切似乎都很好。这是生成的迁移脚本的相关部分:

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

然后当我稍后尝试添加 User:

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

然后我收到以下错误:

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'

我做错了什么吗?

PS。 我正在使用 Entity Framework Core 2.0.

EF Core 2.0 默认为拥有的实体创建一个主键作为影子 属性 因为它支持 table 拆分,因此 UserAddress 属性 在 User 实例中不能为 null,必须定义。

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

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

如果您希望拥有的实体的值为空,则只需定义一个默认实例,即:

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

您可以在此处阅读有关自有实体隐式密钥的更多信息:https://docs.microsoft.com/en-us/ef/core/modeling/owned-entities#implicit-keys

所提供的解决方案在 EF Core 5.0 中对我不起作用。我已将构造函数添加到地址 class

public Address()
{
    Line1 = string.Empty;
}

(至少有一个字段不能为空)。

现在它适用于新的根实体。但我仍然修复数据库中的现有实体

UPDATE RootEntityTable SET Address_Line1 = '' WHERE Id IN (...)