如何删除EF核心代码优先约定PK

时间:2020-10-13 17:51:10

标签: entity-framework-core ef-code-first

我的(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?

0 个答案:

没有答案