EF Core / DbContext > Map custom type as primary key

送分小仙女□ 提交于 2019-12-12 08:53:45

问题


Using the fluent api, how do I map a custom type as the primary key within my OnModelCreating method of the DbContext class?

Using EF Core I'm trying to build a model for the follow entity.

public class Account
{
    public AccountId AccountId { get; }

    public string Name { get; set; }

    private Account()
    {
    }

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

Where the primary key is the AccountId; the type is a simple value object like this.

public class AccountId
{
    public string Id { get; }

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

Within OnModelCreating, I found I can't map the AccountId without having a backing field. So I introduced the backing field _accountId. I don't want the AccountId to have a setter.

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

But I still can't figure out how you specify a property with a backing field which is also the primary key.

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

The OnModelCreating throws an exception on the property map line (account.Property(x => x.AccountId).HasField("_accountId");). Stating that property and field have to be the same type.


回答1:


As pointed out, one can use a custom typed property as entity key by taking advantage of the Value Conversion feature in EF Core 2.1

So in your own example instead of mapping the property to a backing field, you can now define a custom conversion for it like this:

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

As described in the documentation, also a ValueConverter class can be implemented to make the conversion reusable and many custom converters are also provided out of the box.

Note: It's a good idea to implement IComparable and IComparable<T> for your custom AccountId class. Because EF Core seems to sort your changed entities based on their Keys internally for batch operations and you would receive an exception if your Key is not comparable!



来源:https://stackoverflow.com/questions/49607375/ef-core-dbcontext-map-custom-type-as-primary-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!