问题描述
我们使用的是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一起使用的实体类型生成器,所以我看到两个选择:
- 请勿使用流利的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;
});
- 使用内部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();
});