EF Core / DbContext>将地图自定义类型作为主键 [英] EF Core / DbContext > Map custom type as primary key

查看:178
本文介绍了EF Core / DbContext>将地图自定义类型作为主键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

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

OnModelCreating之内,我发现如果没有后备字段,则无法映射 AccountId 。因此,我介绍了后备字段 _accountId 。我不希望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");
}

OnModelCreating在属性映射行上引发异常( 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.

推荐答案

如前所述,可以使用自定义通过利用 值将类型化的属性作为实体键 EF Core 2.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));
}

文档,还可以实现ValueConverter类以使转换可重用,并且还提供了许多自定义转换器

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.

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

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!

这篇关于EF Core / DbContext&gt;将地图自定义类型作为主键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆