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

Chr*_*ray 5 c# dbcontext entity-framework-core .net-core

使用流利的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;            
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public class AccountId
{
    public string Id { get; }

    public AccountId(string accountId)
    {
        Id = accountId;
    }
}
Run Code Online (Sandbox Code Playgroud)

在中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;            
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我仍然不知道如何使用后备字段(也是主键)指定属性。

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");
}
Run Code Online (Sandbox Code Playgroud)

OnModelCreating在属性映射行(account.Property(x => x.AccountId).HasField("_accountId");)上引发异常。说明属性和字段必须是相同的类型。

ami*_*iir 6

正如所指出的,通过利用EF Core 2.1中的值转换功能,可以使用自定义类型属性作为实体键

因此,在您自己的示例中,您现在可以像这样为它定义自定义转换,而不是将属性映射到支持字段:

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

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

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

  • 这是一个好主意,但不适用于多值对象,如此处所述:https://docs.microsoft.com/en-us/ef/core/modeling/value-conversions#limitations (3认同)
  • 我在为`key` 设置转换器时遇到一个问题:如果在添加新实体时类型是`class`,`key` 不能为`null` 并抛出异常;如果类型是一个结构体(所以它不能为空)它可以工作**但是**键不能设置为“自动增量” - 我找不到设置它自动增量的方法。 (3认同)
  • 任何人在将关系构建为单一导航属性时都可以使用此功能(即子项没有与父项相关的属性(https://learn.microsoft.com/en-us/ef/core/modeling/relationships)) ?当我使用 Set&lt;Account&gt;().Include(a =&gt; a.Children)` 时,子集合始终为空。当我将“Id”设置为整数而不是“AccountId”时,我的“Include”就可以工作 (2认同)