EF Core / DbContext>将自定义类型映射为主键

时间:2018-04-02 07:50:37

标签: c# .net-core entity-framework-core dbcontext

使用流畅的api,如何将自定义类型映射为DbContext类的OnModelCreating方法中的主键?

使用EF Core我试图为跟随实体构建模型。

public class Account
{
    public AccountId AccountId { get; }

    public string Name { get; set; }

    private Account()
    {
    }

    public Account(AccountId accountId, string name)
    {
        AccountId = accountId;
        Name = name;            
    }
}

主键是AccountId;类型是一个像这样的简单值对象。

public class AccountId
{
    public string Id { get; }

    public AccountId(string accountId)
    {
        Id = accountId;
    }
}

OnModelCreating内,我发现无法在没有支持字段的情况下映射AccountId。所以我介绍了支持字段_accountId。我不希望AccountId有一个二传手。

public class Account
{
    private string _accountId;
    public AccountId AccountId { get { return new AccountId(_accountId); } }

    public string Name { get; set; }

    private Account()
    {
    }

    public Account(AccountId accountId, string name)
    {
        _accountId = accountId.Id;
        Name = name;            
    }
}

但我仍然无法弄清楚如何使用支持字段指定属性,这也是主键。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    var account = modelBuilder.Entity<Account>();

    account.ToTable("Accounts");
    account.HasKey(x => x.AccountId);
    account.Property(x => x.AccountId).HasField("_accountId");
}

OnModelCreating在属性地图行(account.Property(x => x.AccountId).HasField("_accountId");)上抛出异常。 声明属性和字段必须是同一类型。

1 个答案:

答案 0 :(得分:2)

如前所述,可以利用 EF Core 2.1

中的 Value Conversion 功能将自定义类型的属性用作实体键。

因此,在您自己的示例中,您无需像下面那样将属性映射到支持字段,就可以为它定义自定义转换:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    ...
    account.HasKey(x => x.AccountId);
    account.Property(x => x.AccountId)
        .HasConversion(
            v => v.Id,
            v => new AccountId(v));
}

documentation中所述,还可以实现ValueConverter类以使转换可重用,并且还提供了许多自定义转换器。

注意:为自定义IComparable类实现IComparable<T>AccountId是一个好主意。因为EF Core似乎会在内部根据更改后的实体的键对您更改的实体进行排序,并且如果您的键不具有可比性,您将收到异常!