猿问

实现接口的实体的通用配置

假设我有一些界面,例如:


public interface ISoftDeletable

{

    bool IsActive { get; set }

}

我有很多实体实现了它:


public class Entity1 : ISoftDeletable

{

    public int Id { get; set }

    public bool IsActive { get; set; }

}


public class Entity2 : ISoftDeletable

{

    public int Id { get; set }

    public bool IsActive { get; set; }

}

在OnModelCreating:


protected override void OnModelCreating(ModelBuilder modelBuilder)

{

    modelBuilder.Entity<Entity1>().Property(e => e.IsActive).HasDefaultValue(true);

    modelBuilder.Entity<Entity2>().Property(e => e.IsActive).HasDefaultValue(true);

}

有什么方法可以重构它,以便我可以HasDefaultValue为所有实体进行设置,ISoftDeletable而不是像上面那样做?


我可能可以使用每个实体的默认构造函数解决这个特定情况,IsActive = true甚至创建一个基本抽象类,但我不太喜欢它。


有没有更好的办法?


阿晨1998
浏览 148回答 2
2回答

慕虎7371278

我在这里找到了一些答案:GetEntityTypes: configure entity properties using the generic version of .Property<TEntity> in EF Core除了上面的评论之外,还有一种方法可以不用为每个实体调用它。这可能可以重构为一些扩展方法,正如 Erndob 在我的问题下的评论所提到的。protected override void OnModelCreating(ModelBuilder modelBuilder){&nbsp; &nbsp; foreach (var entityType in modelBuilder.Model.GetEntityTypes())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (typeof(ISoftDeletable).IsAssignableFrom(entityType.ClrType))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Entity(entityType.ClrType).Property<bool>(nameof(ISoftDeletable.IsActive)).HasDefaultValue(true);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}解决方案是使用ModelBuilder.Model.GetEntityTypes()和查找可从ISoftDeletable.在我看来,这比手动配置它甚至创建一个抽象IEntityTypeConfiguration<>类要好得多,因为您不必记住对所有ISoftDeletable类都使用它。更干净的外观:public static class ModelBuilderExtensions{&nbsp; &nbsp; public static ModelBuilder EntitiesOfType<T>(this ModelBuilder modelBuilder,&nbsp; &nbsp; &nbsp; &nbsp; Action<EntityTypeBuilder> buildAction) where T : class&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return modelBuilder.EntitiesOfType(typeof(T), buildAction);&nbsp; &nbsp; }&nbsp; &nbsp; public static ModelBuilder EntitiesOfType(this ModelBuilder modelBuilder, Type type,&nbsp; &nbsp; &nbsp; &nbsp; Action<EntityTypeBuilder> buildAction)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; foreach (var entityType in modelBuilder.Model.GetEntityTypes())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (type.IsAssignableFrom(entityType.ClrType))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buildAction(modelBuilder.Entity(entityType.ClrType));&nbsp; &nbsp; &nbsp; &nbsp; return modelBuilder;&nbsp; &nbsp; }}并且OnModelCreating:protected override void OnModelCreating(ModelBuilder modelBuilder){&nbsp; &nbsp; modelBuilder.EntitiesOfType<ISoftDeletable>(builder =>&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; builder.Property<bool>(nameof(ISoftDeletable.IsActive)).HasDefaultValue(true);&nbsp; &nbsp; &nbsp; &nbsp; // query filters :)&nbsp; &nbsp; &nbsp; &nbsp; var param = Expression.Parameter(builder.Metadata.ClrType, "p");&nbsp; &nbsp; &nbsp; &nbsp; var body = Expression.Equal(Expression.Property(param, nameof(ISoftDeletable.IsActive)), Expression.Constant(true));&nbsp; &nbsp; &nbsp; &nbsp; builder.HasQueryFilter(Expression.Lambda(body, param));&nbsp; &nbsp; });}

白板的微信

我想做类似的事情,但使用IEntityTypeConfiguration界面来保存我的通用配置。我最终不得不使用反射,但它有效:Interface:public interface IHasDisplayId{&nbsp; &nbsp; Guid DisplayId { get; }}EntityTypeConfig:public class HasDisplayIdEntityTypeConfiguration<T> : IEntityTypeConfiguration<T> where T : class, IHasDisplayId{&nbsp; &nbsp; public void Configure(EntityTypeBuilder<T> builder)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; builder.Property(e => e.DisplayId).IsRequired();&nbsp; &nbsp; &nbsp; &nbsp; builder.HasIndex(e => e.DisplayId);&nbsp; &nbsp; }}Extension method:public static ModelBuilder ApplyConfiguration<T>(this ModelBuilder modelBuilder, Type configurationType, Type entityType){&nbsp; &nbsp; if (typeof(T).IsAssignableFrom(entityType))&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Build IEntityTypeConfiguration type with generic type parameter&nbsp; &nbsp; &nbsp; &nbsp; var configurationGenericType = configurationType.MakeGenericType(entityType);&nbsp; &nbsp; &nbsp; &nbsp; // Create an instance of the IEntityTypeConfiguration implementation&nbsp; &nbsp; &nbsp; &nbsp; var configuration = Activator.CreateInstance(configurationGenericType);&nbsp; &nbsp; &nbsp; &nbsp; // Get the ApplyConfiguration method of ModelBuilder via reflection&nbsp; &nbsp; &nbsp; &nbsp; var applyEntityConfigurationMethod = typeof(ModelBuilder)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetMethods()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Single(e => e.Name == nameof(ModelBuilder.ApplyConfiguration)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&& e.ContainsGenericParameters&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&& e.GetParameters().SingleOrDefault()?.ParameterType.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>));&nbsp; &nbsp; &nbsp; &nbsp; // Create a generic ApplyConfiguration method with our entity type&nbsp; &nbsp; &nbsp; &nbsp; var target = applyEntityConfigurationMethod.MakeGenericMethod(entityType);&nbsp; &nbsp; &nbsp; &nbsp; // Invoke ApplyConfiguration, passing our IEntityTypeConfiguration instance&nbsp; &nbsp; &nbsp; &nbsp; target.Invoke(modelBuilder, new[] { configuration });&nbsp; &nbsp; }&nbsp; &nbsp; return modelBuilder;}Usage:protected override void OnModelCreating(ModelBuilder modelBuilder){&nbsp; &nbsp; foreach (var entityType in modelBuilder.Model.GetEntityTypes())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.ApplyConfiguration<IHasDisplayId>(typeof(HasDisplayIdEntityTypeConfiguration<>), entityType.ClrType);&nbsp; &nbsp; }}
随时随地看视频慕课网APP
我要回答