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

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

问题描述

使用 fluent 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 有一个 setter.

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.

推荐答案

正如所指出的,可以利用

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.

注意:为您的自定义 AccountId 类实现 IComparableIComparable 是个好主意.因为 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天全站免登陆