C# 如何减少OnModelCreating中fluentapi的代码
我的表中有几个列不应该在以后的任何更新中更改,因此我在C# 如何减少OnModelCreating中fluentapi的代码,c#,asp.net-core-2.1,entity-framework-core-2.1,C#,Asp.net Core 2.1,Entity Framework Core 2.1,我的表中有几个列不应该在以后的任何更新中更改,因此我在OnModelCreating中创建了fluent API,如下所示 base.OnModelCreating(builder); builder.Entity<UserSetting>() .Property(p => p.ID) .Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore; builder
OnModelCreating
中创建了fluent API,如下所示
base.OnModelCreating(builder);
builder.Entity<UserSetting>()
.Property(p => p.ID)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
builder.Entity<UserSetting>()
.Property(p => p.CreatedOn)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
builder.Entity<UserSetting>()
.Property(p => p.CreatedBy)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
考虑到DRY,我建议您创建自己的扩展方法,如下所示:
public static class ExtensionMethod
{
public static void InmutableCollumn<TEntity, TProperty>(this ModelBuilder modelBuilder, Expression<Func<TEntity, TProperty>> propertyExpression) where TEntity : class
{
modelBuilder.Entity<TEntity>()
.Property(propertyExpression)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
}
}
公共静态类扩展方法
{
MutableCollumn(此ModelBuilder ModelBuilder,Expression propertyExpression)中的公共静态void,其中tenty:class
{
modelBuilder.Entity()
.Property(propertyExpression)
.Metadata.AfterSaveBehavior=PropertySaveBhavior.Ignore;
}
}
那么你可以称之为:
modelBuilder.InmutableCollumn<UserSetting, Guid>(p => p.Id);
modelBuilder.inmutablecolumn(p=>p.Id);
这将使您的代码更易于维护,并且减少重复性
您甚至可以让该方法接收表达式列表,只需要找到一种处理属性类型的方法。看看这个草案:
public static void InmutableCollumn<TEntity>(this ModelBuilder modelBuilder, params Expression<Func<TEntity, object>>[] propertiesExpression) where TEntity : class
{
foreach(var propertyExpression in propertiesExpression)
modelBuilder.Entity<TEntity>()
.Property(propertyExpression)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
}
mutableCollumn(此ModelBuilder ModelBuilder,参数表达式[]propertiesExpression)中的公共静态void,其中TEntity:class
{
foreach(PropertieExpression中的var propertyExpression)
modelBuilder.Entity()
.Property(propertyExpression)
.Metadata.AfterSaveBehavior=PropertySaveBhavior.Ignore;
}
所以它会被这样称呼:
modelBuilder.InmutableCollumn<UserSetting>(p => p.ID, p => p.CreatedOn);
modelBuilder.inmutablecolumn(p=>p.ID,p=>p.CreatedOn);
有很多方法可以做到这一点,最自然的方法是在实现IEntityTypeConfiguration的受约束泛型类中移动公共代码。然后迭代模型实体类型,通过反射实例化配置类,并动态调用ModelBuilder
的ApplyConfiguration
方法(或使用反射)
例如,配置类:
public class CommonEntityTypeConfiguration<TEntity> : IEntityTypeConfiguration<TEntity>
where TEntity : Common
{
public void Configure(EntityTypeBuilder<TEntity> builder)
{
builder.Property(p => p.ID)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
builder.Property(p => p.CreatedOn)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
builder.Property(p => p.CreatedBy)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
}
}
这使您能够流畅地配置基类的所有方面,而不仅仅是某些属性的AfterSaveBehavior
。所有这些表都共享基类或接口吗?是的,所有模型类都来自一个基类。您能在问题中包括该类吗?我猜您希望将上述配置应用于继承该基类的所有类,对吗?使用泛型方法将此繁琐的代码转换为简单方法callMy Qestion更新为基类。引发了一个Un-Handlec异常“Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder)“无法从用法推断。请尝试显式指定类型参数。”@Ramesh抱歉,忘记了非泛型Entity
方法没有返回泛型EntityTypeBuilder
。现在正在工作(已测试:)
public class CommonEntityTypeConfiguration<TEntity> : IEntityTypeConfiguration<TEntity>
where TEntity : Common
{
public void Configure(EntityTypeBuilder<TEntity> builder)
{
builder.Property(p => p.ID)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
builder.Property(p => p.CreatedOn)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
builder.Property(p => p.CreatedBy)
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
}
}
var entityTypes = modelBuilder.Model.GetEntityTypes()
.Where(t => typeof(Common).IsAssignableFrom(t.ClrType));
foreach (var entityType in entityTypes)
{
var configurationType = typeof(CommonEntityTypeConfiguration<>)
.MakeGenericType(entityType.ClrType);
modelBuilder.ApplyConfiguration(
(dynamic)Activator.CreateInstance(configurationType));
}