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

C# 实现接口的实体的通用配置,c#,entity-framework-core,C#,Entity Framework Core,假设我有一些界面,比如: 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 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; }
}
在创建模型时的

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Entity1>().Property(e => e.IsActive).HasDefaultValue(true);
    modelBuilder.Entity<Entity2>().Property(e => e.IsActive).HasDefaultValue(true);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.EntitiesOfType<ISoftDeletable>(builder =>
    {
        builder.Property<bool>(nameof(ISoftDeletable.IsActive)).HasDefaultValue(true);

        // query filters :)
        var param = Expression.Parameter(builder.Metadata.ClrType, "p");
        var body = Expression.Equal(Expression.Property(param, nameof(ISoftDeletable.IsActive)), Expression.Constant(true));
        builder.HasQueryFilter(Expression.Lambda(body, param));
    });
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().Property(e=>e.IsActive).HasDefaultValue(true);
modelBuilder.Entity().Property(e=>e.IsActive).HasDefaultValue(true);
}
有没有办法重构它,这样我就可以为实现
ISoftDeletable
的所有实体设置
hasdaultvalue
,而不是像上面这样做

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

类似问题:


有没有更好的办法?

我在这里找到了一些答案:

除了上面的评论之外,还有一种方法可以不为每个实体调用它。正如Erndob在我的问题中的评论所提到的,这可能会被重构为某种扩展方法

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    {
        if (typeof(ISoftDeletable).IsAssignableFrom(entityType.ClrType))
        {
            modelBuilder.Entity(entityType.ClrType).Property<bool>(nameof(ISoftDeletable.IsActive)).HasDefaultValue(true);
        }
    }
}
关于模型创建

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Entity1>().Property(e => e.IsActive).HasDefaultValue(true);
    modelBuilder.Entity<Entity2>().Property(e => e.IsActive).HasDefaultValue(true);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.EntitiesOfType<ISoftDeletable>(builder =>
    {
        builder.Property<bool>(nameof(ISoftDeletable.IsActive)).HasDefaultValue(true);

        // query filters :)
        var param = Expression.Parameter(builder.Metadata.ClrType, "p");
        var body = Expression.Equal(Expression.Property(param, nameof(ISoftDeletable.IsActive)), Expression.Constant(true));
        builder.HasQueryFilter(Expression.Lambda(body, param));
    });
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.EntitiesOfType(builder=>
{
builder.Property(nameof(ISoftDeletable.IsActive)).HasDefaultValue(true);
//查询筛选器:)
var param=Expression.Parameter(builder.Metadata.ClrType,“p”);
var body=Expression.Equal(Expression.Property(param,nameof(ISoftDeletable.IsActive)),Expression.Constant(true));
haskqueryfilter(Expression.Lambda(body,param));
});
}

我想做一些类似的事情,但使用
IEntityTypeConfiguration
界面保存我的通用配置。我最终不得不使用反射,但它是有效的:

接口

public interface IHasDisplayId
{
    Guid DisplayId { get; }
}
EntityTypeConfig

public class HasDisplayIdEntityTypeConfiguration<T> : IEntityTypeConfiguration<T> where T : class, IHasDisplayId
{
    public void Configure(EntityTypeBuilder<T> builder)
    {
        builder.Property(e => e.DisplayId).IsRequired();
        builder.HasIndex(e => e.DisplayId);
    }
}
用法

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    {
        modelBuilder.ApplyConfiguration<IHasDisplayId>(typeof(HasDisplayIdEntityTypeConfiguration<>), entityType.ClrType);
    }
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
foreach(modelBuilder.Model.GetEntityTypes()中的var entityType)
{
modelBuilder.ApplyConfiguration(typeof(HasDisplayIdEntityTypeConfiguration),entityType.ClrType);
}
}

扩展方法?仍然需要列出需要绑定的每个实体,但不需要继续执行Property.HasDefaultValue。是否在实体类中使用自动属性初始值设定项<代码>公共bool IsActive{get;set;}=true或“inverse”将属性名称改为类似“IsDeleted”的名称,这样它会自动获得正确的默认值。不过,使用带有属性和默认值的抽象类看起来是个不错的选择。不确定你为什么不想要它。然后你在另一个问题中有了这个选项,一个基本配置类,它将设置你需要的。如果您不想改变整个结构的配置方式并引入新的配置类,那么留给您的是一个扩展方法选项,它将至少部分地抽象它但是EF6没有
HasDefaultValue
,我不知道EF Core是否仍然支持
类型
configuration.Nice。也不知道你可以简单地用字符串选择属性@Erndob是的,如果在action参数中使用generic
EntityTypeBuilder
,则会更干净,但这需要使用reflection@Konrad我尝试使用通用的
EntityTypeBuilder
,因为它看起来是一个很好的解决方案,但遇到了一个问题。当我通过反射从
ModelBuilder
Entity()
System.ArgumentException:指定的类型“IExample”必须是非接口引用类型,才能用作实体类型
,因此可能不可能:/@我不记得了。但我的扩展方法在我上次做的时候对接口很好。不知道在3.0+ahhh ClrType中是否发生了变化-这就是我出错的地方,谢谢你!!!