自动按约定映射加上拥有的实体

Automatic by convention mapping coupled with Owned entities

我们正在使用 ef core 3.1.6。我们的实体有两个特殊接口。

ICreatedIUpdated

从数据库上下文中,我们使用

自动为这些添加配置
protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    builder.ApplyConfigurationsFromAssembly(typeof(ICreated).Assembly);

    builder
        .Model
        .GetEntityTypes()
        .Where(et => typeof(IUpdated).IsAssignableFrom(et.ClrType))
        .ForEach(et => builder.Entity(et.ClrType).Property(nameof(IUpdated.UpdatedUTC)).IsConcurrencyToken());

    builder
        .Model
        .GetEntityTypes()
        .Where(et => typeof(ICreated).IsAssignableFrom(et.ClrType))
        .ForEach(et =>
        {
            var entity = builder
                .Entity(et.ClrType);

            entity
                .Property(nameof(ICreated.CreatedUTC))
                .IsRequired();

            entity.Property(nameof(ICreated.CreatedBy))
                .IsRequired();
        })
}

到目前为止,这种方法运行良好。但现在我们想添加一个 ICreated 实体作为拥有的实体做

builder.OwnsOne(p => p.PayerInfo, b =>
{
    b.WithOwner().HasForeignKey(p => p.PaymentTransactionId);
    b.ToTable("PaymentTransactionPayerInfo", "dbo");
});

如果我们不添加 ICreated 接口,这将起作用。如果我们将接口添加到实体,它将在此行崩溃 builder.Entity(et.ClrType) 例外情况

The type 'PaymentTransactionPayerInfo' cannot be configured as non-owned because an owned entity type with the same name already exists

所以对于这些我需要以某种方式使用 OwnedNavigationBuilder。想法?谢谢

由于 EF Core 不允许您使用 Entity 方法来获取实体类型生成器以与 fluent APIs 一起使用,我看到两个选项:

  1. 不要使用 fluent API,直接使用可变元数据 API 执行配置,例如:
builder
    .Model
    .GetEntityTypes()
    .Where(et => typeof(IUpdated).IsAssignableFrom(et.ClrType))
    .ForEach(et =>
    { 
        et.FindProperty(nameof(IUpdated.UpdatedUTC))
            .IsConcurrencyToken = true;
    });

builder
    .Model
    .GetEntityTypes()
    .Where(et => typeof(ICreated).IsAssignableFrom(et.ClrType))
    .ForEach(et =>
    {
        et.FindProperty(nameof(ICreated.CreatedUTC))
            .IsNullable = false;

        et.FindProperty(nameof(ICreated.CreatedBy))
            .IsNullable = false;
    });
  1. 冒一点风险使用内部 API(不知道为什么他们把它变成内部 w/o 提供一种 public 获得所需构建器的方法)。

添加

using Microsoft.EntityFrameworkCore.Metadata.Internal;

这将使您能够访问 AsEntityType() 扩展方法,并且返回的类型具有 属性 Builder 返回流畅调用所需的实体类型构建器:

builder
    .Model
    .GetEntityTypes()
    .Where(et => typeof(IUpdated).IsAssignableFrom(et.ClrType))
    .ForEach(et => et.AsEntityType().Builder // <--
        .Property(nameof(IUpdated.UpdatedUTC)).IsConcurrencyToken());

builder
    .Model
    .GetEntityTypes()
    .Where(et => typeof(ICreated).IsAssignableFrom(et.ClrType))
    .ForEach(et =>
    {
        var entity = et.AsEntityType().Builder; // <--

        entity
            .Property(nameof(ICreated.CreatedUTC))
            .IsRequired();

        entity.Property(nameof(ICreated.CreatedBy))
            .IsRequired();
    });