DanielAlmeida
DanielAlmeida

Reputation: 33

Entity Framework property hiding

I'm working with Entity Framework 6.0.2 Code First with Sql Server.

I have a base class called Entity and since we can't extend enums I need to redefine a property type for another class called Company, so I'm using the new keyword to hide the base property and redefine it.

public interface IEntity 
{
    Guid Id { get; set; }
    State State { get; set; }
}

public abstract class Entity : IEntity
{
   public Guid Id { get; set; }
   public State State { get; set; }
}

public enum State 
{
   Inactive = 0,
   Active = 1
}

public class Company : Entity 
{
   public new CompanyState State { get; set; }
   public string SomeOtherProp { get; set; }
}

public enum CompanyState 
{
   Inactive = 0,
   Active = 1,
   Extra = 2
}

The problem I get is when Entity Framework is trying to create the DbContext it crashes with this error: "The item with identity 'State' already exists in the metadata collection. Parameter name: item"

I have a workaround: I could change the State propery in Entity class to int and cast the appropriate enum to int, but I think I'll lose type safety / restriction that the enums have.

I'd like to change the metadata info to avoid this error but I don't know how.

Upvotes: 3

Views: 4890

Answers (2)

bubi
bubi

Reputation: 6501

Just for exposing another way you could also use this model with an hidden backing field and not mapped states

public interface IEntity
{
    int Id { get; set; }
    State State { get; set; }
}

public abstract class Entity : IEntity
{
    protected int InternalState { get; set; }
    public int Id { get; set; }

    [NotMapped]
    public State State
    {
        get { return (State) InternalState; }
        set { InternalState = (int) value; }
    }

    // Entity is not a POCO class because of this :(
    // If we want to hide InternalState this is the only way to map it
    public class EntityMap : EntityTypeConfiguration<Entity>
    {
        public EntityMap()
        {
            // Properties
            Property(t => t.InternalState)
                .HasColumnName("State");
        }
    }
}

public enum State
{
    Inactive = 0,
    Active = 1
}

public class Company : Entity
{
    [NotMapped]
    public new CompanyState State
    {
        get { return (CompanyState)InternalState; }
        set { InternalState = (int)value; }
    }
    [MaxLength(50)]
    public string SomeOtherProp { get; set; }
}

public class Employee : Entity
{
    [MaxLength(50)]
    public string SomeOtherProp { get; set; }
}

public enum CompanyState
{
    Inactive = 0,
    Active = 1,
    Extra = 2
}

Upvotes: 0

David Leitner
David Leitner

Reputation: 3382

This guy here found a solution for some similar problem.

Neither your, nor his solution is nice. It is and remains a hack. I would go with the solution you already mentioned. Change the state to stateId. And add a State Property to your Entity:

public State State {get {return (State)stateId;}

In your Company override this Property with new:

public new CompanyState State {get {return (CompanyState )stateId;}

But I think best solution would be, to change your inheritance hierarchy. I think either your IEntity should not have a state, or your company should not inherit from Entity.

Upvotes: 1

Related Questions