I’m trying to incorporate EF in my application. I use EF6 and Code First. My object model has some generic classes and it seems that Code First accepts it partially (tables and columns are generated correctly).
Below an example:
public class Group : TimeableObject<GroupTimeline> {}
public class GroupTimeline : TimelineBase
{
public GroupTimeline() { }
public string Name {get; set;}
}
public abstract class TimelineBase
{
public int Id { get; set; }
public DateTime BeginDate { get; set; }
public DateTime EndDate { get; set; }
}
public abstract class TimeableObject<T>
where T : TimelineBase
{
private DateTime? _snapshotDate;
public TimeableObject()
{
Timelines = new List<T>();
}
public int Id { get; set; }
public DateTime BeginDate { get; set; }
public DateTime EndDate { get; set; }
public List<T> Timelines { get; set; }
public DateTime SnapshotDate
{
get { //some logic.. }
set { _snapshotDate = value; }
}
public T Timeline
{
get { //some logic.. }
}
}
Through fluent API I configured the inheritance as TPC. So I expect a table Groups and a table GroupTimeline with a foreign key to Groups in GroupTimeline.
First of all, the generated database looks correct except for the identity. The strange thing about this is that EF sees the Id property in e.g. Group and generates a PK in the database. Althought without an identity. The same for the Id property in the TimelineBase class. Second, I don't want the property SnapshotDate to be mapped. Through fluent API I was not able to reach this. Here I get an exception telling me that the complete class is ignored or is a generic. So I assume that EF does not support generic classes although the database is generated correctly (not the identity). What's the story behind this?? With the use of data annotations I fixed my issues. I can get an identity with the attributes (on the Id property):
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
and I can prevent mapping the SnapshotDate property with:
[NotMapped]
below my fluent configuration:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Group>().Map(m =>
{
m.MapInheritedProperties();
});
modelBuilder.Entity<GroupTimeline>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Group_Timeline");
});
modelBuilder.Entity<TimeableObject<TimelineBase>>().HasKey(m => m.Id).Property( p => p.Id ).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<TimeableObject<TimelineBase>>().Ignore(m => m.SnapshotDate);
modelBuilder.Entity<TimelineBase>().HasKey(m => m.Id).Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
This throw's an exception:
The type 'Data.DataObjectModel.TimeableObject`1[Data.DataObjectModel.TimelineBase]'
was not mapped. Check that the type has not been explicitly excluded by using the
Ignore method or NotMappedAttribute data annotation. Verify that the type was
defined as a class, is not primitive or generic, and does not inherit from
EntityObject.
Regards, Daniel Kaya