EF4 CTP5 How To? Map an inherited Property to a field in a related table

431 views Asked by At

i defined an entity called Variable and derived classes by using Table Per Hierarchy (TPH). The Base class "Variable" contains a collection of PropertyValues:

private ICollection<PropertyValue> propertyValues;

public const string DiscriminatorColumn = "Discriminator";
public const string Table = "Variables";

public VariableType VariableType { get; set; }
public string Name { get; set; }

[NotMapped]
public string Discriminator { get; set; }

public virtual ICollection<PropertyValue> PropertyValues
{
    get { return this.propertyValues ?? (this.propertyValues = new ObservableCollection<PropertyValue>()); }
    set { SetProperty(ref this.propertyValues, value, () => PropertyValues); }
}

Now, i want to derive a SpecialVariable class (or more than one), which define some SpecialProperties (e.g. HighLimit) which should be mapped to an entry in the PropertyValues (table).

public class MySpecialVariabe : Variable
{
    public double HighLimit { get; set; }
}

My OnModelCreating function looks currently like this:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Variable>().HasKey(x => new { x.Id });

    modelBuilder.Entity<Variable>()
        .Map<MySpecialVariabe>(m => m.Requires(Variable.DiscriminatorColumn).HasValue(typeof(MySpecialVariabe).Name))
        .Map<MySpecialVariabe2>(m => m.Requires(Variable.DiscriminatorColumn).HasValue(typeof(MySpecialVariabe2).Name)).ToTable(Variable.Table);
}

Can someone give me some tips how to realize this, without writing tons of bad looking code in the derived class. (Performance is not that important.)

best regards,

Chris

1

There are 1 answers

1
Ladislav Mrnka On BEST ANSWER

You can't map properties to records. That is how I understand your question. You have some PropertyValues table which is most probably some Key/Value pair and you want to map entity properties as records (data) to this table. This is not something which EF do for you. You must provide not mapped properties which will work with correct record in propertyValues collection.

Something like:

[NotMapped]
public double HighLimit
{
  get
  {
    var current = propertyValues.SingleOrDefault(p => p.Key == "HighLimit");
    return current != null ? current.Value : 0.0;
  }
  set 
  {
    var current = propertyValues.SingleOrDefault(p => p.Key == "HighLimit");
    if (current != null)
    {
      current.Value = value;
    }
    else
    {
      propertyValues.Add(new PropertyValue { Key = "HighLimit", Value = value });
    }
  }
}

The problem with this approach is that you can't use HighLimit in Linq-to-entities queries - you must always use PropertyValues.

Moreover TPH in EF requires that properties of derived entity (MySpecialVariable) are mapped to the same table as parent entity (Variable). You can't map properties of derived entity into data stored in other table (PropertyValues).