demo
demo

Reputation: 6235

How do I override base classes field functionality?

Well, I have BaseModel

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

Also i have model Update

public class Update : BaseModel
{
    public DateTime Updated { get; set; }
}

which is derived from BaseModel In BaseModel Id field is not incremented, but for Update model I need Id with Identity.

Can I add new field to Update like UpdateId which will be incremented, but remove field Id?


Is it possible solution? :

How about just declare models in next way

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

and

public class Update : BaseModel
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public DateTime Updated { get; set; }
}

Id in Update will override Id in BaseModel

Upvotes: 4

Views: 1370

Answers (3)

Sherif Ahmed
Sherif Ahmed

Reputation: 1946

well you can hide the Id from the BaseModel in the UpdateModel public class UpdateModel : BaseModel { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public new int Id { get; set; } public DateTime Updated { get; set; } }

EDIT

Based on the comments the above solution is totally wrong from the programmatic point of view because the backing field Id if you cast any entity derived from UpdateModel to BaseModel will be empty although it will compile and gives the desired result.

check the below solution

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);
    }
}

Upvotes: 1

Yacoub Massad
Yacoub Massad

Reputation: 27861

In your context class (that inherits from DbContext), you can override the settings for the Update entity by overriding the OnModelCreating method like this:

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

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

}

Quoting from this reference:

You can further configure your model by using data annotations or the fluent API. Precedence is given to configuration through the fluent API followed by data annotations and then conventions.

This means that you can override data annotation configuration with the fluent API (via OnModelCreating).

Upvotes: 1

Ivan Stoev
Ivan Stoev

Reputation: 205619

You can use the following technique (heavily used in Windows Forms controls to apply different attributes to the one and the same property):

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

public class Update : BaseModel
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public override int Id { get { return base.Id; } set { base.Id = value; } }
    public DateTime Updated { get; set; }
}

Upvotes: 3

Related Questions