使用反射进行该约定的可能方法是:从 DbContext 类的 DBSet 属性中获取实体类型然后获取实体类型的属性(列)
所以在您的 DbContext 类中添加以下行:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//see below for this extension method
this.ApplyCaseMappingRule(modelBuilder);
base.OnModelCreating(modelBuilder);
}
扩展方法来源:
public static class Extensions
{
public static void ApplyCaseMappingRule<TDbContext>(this TDbContext _, ModelBuilder modelBuilder) where TDbContext:DbContext
{
var ignoreType = typeof(NotMappedAttribute);
var dbSetProps = typeof(TDbContext).GetProperties();
foreach (var dbSetProp in dbSetProps)
{
if (dbSetProp.PropertyType.TryGetEntityTypeFromDbSetType(out var entityType))
{
modelBuilder.Entity(entityType, option =>
{
option.ToTable(Mutate(dbSetProp.Name));
var props = entityType.GetProperties();
foreach (var prop in props)
{
//check if prop has Ignore attribute
var hasIgnoreAttribute =
prop.PropertyType.CustomAttributes.Any(x => x.AttributeType == ignoreType);
if (hasIgnoreAttribute) continue;
option.Property(prop.PropertyType, prop.Name).HasColumnName(Mutate(prop.Name));
}
});
}
}
}
private static bool TryGetEntityTypeFromDbSetType(this Type dbSetType, out Type entityType)
{
entityType = null;
if (dbSetType.Name != "DbSet`1") return false;
if (dbSetType.GenericTypeArguments.Length != 1) return false;
entityType = dbSetType.GenericTypeArguments[0];
return true;
}
public static IEnumerable<string> SplitCamelCase(this string source)
{
const string pattern = @"[A-Z][a-z]*|[a-z]+|\d+";
var matches = Regex.Matches(source, pattern);
foreach (Match match in matches)
{
yield return match.Value;
}
}
public static string Mutate(string propName)
{
return string.Join("_", propName.SplitCamelCase().Select(x => x.ToUpperInvariant()));
}
使用 EF 5.0.0 在 .NET 5 上测试