自动按惯例映射与拥有的实体结合

问题描述

我们使用的是ef核心3.1.6。我们的实体有两个特殊的界面。

ICreated IUpdated

在数据库上下文中,我们使用以下命令自动添加这些配置

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)这一行上崩溃,但例外情况

“ PaymentTransactionPayerInfo”类型无法配置为 非拥有的,因为拥有相同名称的拥有实体类型 存在

因此,我需要以某种方式使用OwnedNavigationBuilder。有想法吗?谢谢

解决方法

由于EF Core不允许您使用Entity方法来获取要与流畅的API一起使用的实体类型生成器,所以我看到两个选择:

  1. 请勿使用流利的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的风险很小(不知道为什么要使其内部不提供提供所需构建器的公共方式)。

添加

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

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...