The Question:
My question is if I'm going about this correctly, or whether there's a tidier/more-robust way of mapping entities with Fluent API? Mainly, should I be doing all the mapping within the overidden OnModelCreating
method? Secondly, is there any reason not to do it this way? And finally, if my datamodel is working, and I'm able to successfully access the database, why would Entity Framework Power Tools not be able to generate a read-only .edmx file?
Here's the back-story and examples of what I'm doing:
So I have a working code-first data model of ~70 very interconnected entities. I reverse engineered it from an existing database that had been using and Entity-Framework designer to relate objects and map them to the SQL db.
I modeled my approach on the tutorials I've done, and I'm using Fluent API for mapping, not Data Annotations.
So I have all the entity models defined as POCOs, each in their own source file. I have another class inheriting DbContext
, we'll call this MyDb
. Inside MyDb
I have the ~70 DbSet
properties
public virtual DbSet<SomeEntity> SomeEntities{ get; set; }
public virtual DbSet<OtherEntity> OtherEntities{ get; set; }
//...You get the idea, there another few dozen of these below
public virtual DbSet<LastEntity> LastEntities{ get; set; }
//Well that was tedious
Following the DbSet
s that provide access to all the entities, I have ~6000 lines of fluent API mappings inside protected override void OnModelCreating(DbModelBuilder mb)
, which is how I learned to do it in the examples, and in the smaller test projects I've done.
protected override void OnModelCreating(DbModelBuilder mb)
{
mb.Entity<SomeEntity>()
.ToTable("SomeEntities")
.HasKey(se => se.ID);
mb.Entity<SomeEntity>()
.Property(se => se.ID)
.HasColumnName("ID")
.HasColumnType("bigint")
.IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
mb.Entity<SomeEntity>()
.Property(se => se.Contents)
.HasColumnName("Content")
.HasColumnType("varchar")
.IsMaxLength()
.IsUnicode(true)
.IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
mb.Entity<SomeEntity>()
.HasMany(se => se.OtherEntities)
.WithRequired(oe => oe.SomeEntity)
.HasForeignKey(oe => oe.SomeEntity_ID);
//and so on, there are another ~70 of these that go on for the
//next 6000 lines
}
Obviously all my entities aren't this simple, and there are many that are unconventional in their property naming, table naming, table types, and so on; that's why I've been quite verbose with the Fluent API.