C# 如何覆盖基类字段功能?

C# 如何覆盖基类字段功能?,c#,.net,entity-framework,ef-code-first,C#,.net,Entity Framework,Ef Code First,嗯,我有BaseModel public class BaseModel { [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id { get; set; } public bool Deleted { get; set; } } 此外,我还有型号更新 public class Update : BaseModel { public DateTime Updated { get; set;

嗯,我有
BaseModel

public class BaseModel
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public bool Deleted { get; set; }
}
此外,我还有型号
更新

public class Update : BaseModel
{
    public DateTime Updated { get; set; }
}
它来自于
BaseModel
BaseModel
中,
Id
字段不会增加,但对于
Update
模型,我需要
Id
Identity

我可以向
Update
添加新字段,比如
UpdateId
,该字段将递增,但删除字段
Id


这是可能的解决方案吗

用下一种方法声明模型怎么样

public class BaseModel
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public bool Deleted { get; set; }
}

Update
中的
Id
将覆盖
BaseModel
public class BaseModel
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }
    public bool Deleted { get; set; }
}
您可以在
UpdateModel

公共类UpdateModel:BaseModel
{
[数据库生成(DatabaseGeneratedOption.Identity)]
public new int Id{get;set;}
公共日期时间已更新{get;set;}
}

编辑 根据注释,从编程的角度来看,上述解决方案是完全错误的,因为如果将从
UpdateModel
派生的任何实体强制转换为
BaseModel
,则支持字段
Id
将为空,尽管它将编译并给出所需的结果

检查下面的解决方案

public class BaseEntity
{
    public int Id { get; set; }
    public bool Deleted { get; set; }
}
public class UpdateEntity : BaseEntity
{
    public DateTime Updated { get; set; }
}

public class Entity1 : BaseEntity
{
    public string Name { get; set; }
}
public class Entity2 : UpdateEntity
{
    public string Name { get; set; }
}

public abstract class BaseEntityTypeConfiguration<T> : EntityTypeConfiguration<T>
    where T : BaseEntity
{
    public BaseEntityTypeConfiguration()
    {
        Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }
}

public abstract class UpdateEntityTypeConfiguration<T> : EntityTypeConfiguration<T>
    where T : UpdateEntity
{
    public UpdateEntityTypeConfiguration()
    {
        Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}

public class Entity1Configuration : BaseEntityTypeConfiguration<Entity1>
{
    public Entity1Configuration()
        : base()
    {
        Property(x => x.Name).HasMaxLength(100);
    }
}
public class Entity2Configuration : UpdateEntityTypeConfiguration<Entity2>
{
    public Entity2Configuration()
        : base()
    {
        Property(x => x.Name).HasMaxLength(100);
    }
}

public class MyDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        var typesToRegister = from type in Assembly.GetExecutingAssembly().GetTypes()
                              where !string.IsNullOrEmpty(type.Namespace) &&
                                    type.BaseType != null &&
                                    type.BaseType.IsGenericType
                              let genericType = type.BaseType.GetGenericTypeDefinition()
                              where genericType == typeof(BaseEntityTypeConfiguration<>) || genericType == typeof(UpdateEntityTypeConfiguration<>)
                              let genericArgument = type.BaseType.GetGenericArguments().FirstOrDefault()
                              where genericArgument != null && genericArgument.BaseType != null &&
                              (genericArgument.BaseType == typeof(BaseEntity) || genericArgument.BaseType == typeof(UpdateEntity))
                              select type;

        foreach (var type in typesToRegister)
        {
            dynamic configurationInstance = Activator.CreateInstance(type);
            modelBuilder.Configurations.Add(configurationInstance);
        }

        base.OnModelCreating(modelBuilder);
    }
}
公共类基本实体
{
公共int Id{get;set;}
公共bool已删除{get;set;}
}
公共类更新属性:BaseEntity
{
公共日期时间已更新{get;set;}
}
公共类Entity1:BaseEntity
{
公共字符串名称{get;set;}
}
公共类Entity2:UpdateEntity
{
公共字符串名称{get;set;}
}
公共抽象类BaseEntityTypeConfiguration:EntityTypeConfiguration
其中T:BaseEntity
{
public BaseEntityTypeConfiguration()
{
属性(x=>x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
}
公共抽象类UpdateEntityTypeConfiguration:EntityTypeConfiguration
其中T:UpdateEntity
{
public UpdateEntityTypeConfiguration()
{
属性(x=>x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
公共类Entity1配置:BaseEntityTypeConfiguration
{
公共实体1配置()
:base()
{
属性(x=>x.Name).HasMaxLength(100);
}
}
公共类Entity2Configuration:UpdateEntityTypeConfiguration
{
公共实体2配置()
:base()
{
属性(x=>x.Name).HasMaxLength(100);
}
}
公共类MyDbContext:DbContext
{
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
var typesToRegister=来自Assembly.getExecutionGassembly().GetTypes()中的类型
其中!string.IsNullOrEmpty(type.Namespace)&&
type.BaseType!=null&&
type.BaseType.IsGenericType
让genericType=type.BaseType.GetGenericTypeDefinition()
其中genericType==typeof(BaseEntityTypeConfiguration)| | genericType==typeof(UpdateEntityTypeConfiguration)
让GenericArguments=type.BaseType.GetGenericArguments().FirstOrDefault()
其中genericArgument!=null&&genericArgument.BaseType!=null&&
(genericArgument.BaseType==typeof(BaseEntity)| | genericArgument.BaseType==typeof(UpdateEntity))
选择类型;
foreach(TypeStoreRegister中的变量类型)
{
dynamic configurationInstance=Activator.CreateInstance(类型);
modelBuilder.Configurations.Add(configurationInstance);
}
基于模型创建(modelBuilder);
}
}

您可以使用以下技术(在Windows窗体控件中大量使用,将不同属性应用于同一个属性):

在您的上下文类(继承自
DbContext
)中,您可以通过覆盖
OnModelCreating
方法来覆盖
Update
实体的设置,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<Update>()
        .Property(x => x.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
基于模型创建(modelBuilder);
modelBuilder.Entity()
.Property(x=>x.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
引述自:

您可以使用数据注释或fluent API进一步配置模型。优先权通过fluent API分配给配置,然后是数据注释和约定


这意味着您可以使用fluent API(通过
OnModelCreating
)覆盖数据注释配置。

是否有从
BaseModel
继承的实体不需要
DatabaseGenerateOption.Identity
?@YacoubMassad,是的,我有3个以上的实体,这应该没有标识Keyword
new
-这里需要它吗?只是为了从BaseModel中隐藏Inherted Id属性@这是不正确的“解决方案”。“UpdateModel”类将有2个Id属性(和支持字段),通过基类转换获取/设置的属性将不同于通过派生类获取/设置的属性。这会导致奇怪的错误和行为。这只是一个错误的设计。@IvanStoev,我已经从这个实体生成了一个表,它只创建了一个字段为
Id
@的列。演示表正常,内存表示不正常。不管怎样,这取决于你。我不是说你应该选我的-雅库布·马萨德方案可能更好。这是最糟糕的,我永远不会在生产代码中使用这样的代码。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<Update>()
        .Property(x => x.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

}