1
votes

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 DbSets 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.

2

2 Answers

2
votes

@Gert Arnold did a good job of answering your first questoins. Regarding the EF Power Tools, they're probably just getting hung up while trying to discover your model. You can do the same thing manually using the following code snippet.

using (var db = new MyContext())
using (var writer = XmlWriter.Create("MyContext.edmx"))
{
    EdmxWriter.WriteEdmx(db, writer);
}
1
votes

I think in terms of performance there's not a markable difference whether you do the configuration by separate EntityTypeConfiguration classes or in OnModelCreating only.

But computer languages were not invented to help computers, but us, binary dyslectic types. Therefore, I would prefer EntityTypeConfigurations, because that helps you to get to a specific mapping quicker than scrolling through 6000 lines of code. We developers spend a lot of time referring back to what we or others wrote before.

I think the issue about EF Power Tools not generating a read-only .edmx file should be a different question. It requires more details on that specific problem.