我的(EF Core 3.1)模型中的许多实体都源自相同的基本类型(HistorizedBaseEntity
),因此应具有相同的PK:
{int ID, Guid InstanceGuid, Instant Time}
我不必为每个实体类型重新定义此代码,而是编写了一些代码来自动处理此问题:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
foreach (var mutableEntityType in modelBuilder.Model.GetEntityTypes().ToList())
{
if (mutableEntityType.ClrType.IsSubclassOf(typeof(BaseEntity))
&& mutableEntityType.BaseType == null)
{
var mutableKeys = mutableEntityType.GetKeys().ToList();
foreach (var mutableKey in mutableKeys)
{
if (mutableKey.IsPrimaryKey() && mutableKey.Properties.Count == 1
&& mutableKey.Properties.First().Name == nameof(IHasId.Id))
mutableEntityType.RemoveKey(mutableKey);
}
if (mutableEntityType.ClrType.IsSubclassOf(typeof(HistorizedBaseEntity))
&& mutableEntityType.BaseType == null)
{
if (!mutableKeys.Any(m => m.Properties.Select(p => p.Name)
.ToHashSet().SetEquals(HistorizedBaseEntity.PrimaryKeyNames)))
{
var keyProperties = mutableEntityType.GetProperties()
.Where(p => HistorizedBaseEntity.PrimaryKeyNames.Contains(p.Name)).ToList();
mutableEntityType.SetPrimaryKey(keyProperties);
}
}
}
}
}
HistorizedBaseEntity:
public class HistorizedBaseEntity
{
public int Id { get; set; }
public Guid InstanceGuid { get; set; }
public Instant Time { get; set; }
public static IReadOnlyList<string> PrimaryKeyNames =>
new List<string> {nameof(Id), nameof(InstanceGuid), nameof(Time)}.AsReadOnly();
}
没有上面的代码,所有源自HistorizedBaseEntity的实体都具有一个以“ ID”作为字段的约定PK。
上面的代码运行后,我确实有2个键,约定基于一个键作为PK,而新创建的一个键作为唯一键。 通过调试,我看到RemoveKey()实际上删除了PK-然后在ConventionDispatcher.OnKeyRemoved中运行KeyDiscoveryConvention,将其重新添加回去。
如何在不禁用约定的情况下删除基于约定的PK?