3

I'm planning on using the Entity Framework 4.1 in my next project, but I'm having trouble finding a good way to go about it. In short, I want to build a multi-tiered application in which the entities will be travelling through web services, and to keep it all as clean as possible I want to use POCO's rather than self tracking entities. Also, there already exists a SQL 2008 database that will be used to base the entities on.

From what I've read so far (from Julie Lerman's article on http://msdn.microsoft.com/nl-nl/magazine/hh148150%28en-us%29.aspx, amongst others), it seems that:

  • If you use the Database First approach, you get a beautiful .edmx to edit your model in, but you'll always end up with persistence-aware objects rather than POCO's, which is not useful in my situation.
  • If you use the Code First approach, the "ADO.NET DbContext generator" only partially helps you: it does generate entities from the .edmx, but it doesn't generate the code required to get the foreign keys and cardinality correct. This means that the code will not work out-of-the-box (-edit, not true, see my post below-), you either have to
    • a) use Data Annotations on your POCO's, which is ugly imo because it pollutes the POCO's with database information and also creates a dependency on the EntityFramework assembly.
    • b) use the DbModelBuilder passed to DbContext.OnModelCreating to set the correct foreign key, mapping etc. information (i.e. the 'fluent' API). And even though the API may be 'fluent', it's still pretty hard (and probably unmaintainable) to set all this information correctly so that it matches the existing database (see http://sessionfactory.blogspot.com/2011/04/conventions-in-entity-framework-41.html for some examples of this).

I realize that the reason why the "DbModelBuilder-way" requires so much effort is because it was designed to be used the other way around: you're supposed to generate the database from the Entity definitions, not try to tweak all Entities so that they (hopefully) match an already existing database. However, it seems to me that the "DbModelBuilder-way" will, in the end, produce the best result: pure POCO's with no database metadata in them.

Now, having said all this, my question is:
Does anyone know of a way to load an .edmx into the DbModelBuilder, so that the foreign key, column mapping and other information doens't need to be specified by hand through the fluent API?

I think that this would be the best of both worlds, because you can visually edit the mapping like you would in the Database First scenario, and still get clean POCO's because all required metadata is stored in the DbModelBuilder.

Leon Bouquiet
  • 4,159
  • 3
  • 25
  • 36

3 Answers3

1

Man what are you talking about?

If you use the Database First approach, you get a beautiful .edmx to edit your model in, but you'll always end up with persistence-aware objects rather than POCO's, which is not useful in my situation.

That is not true. EDMX can produce almost everything code first can and even many things which code first can't.

If you use the Code First approach, the "ADO.NET DbContext generator" only partially helps you: it does generate entities from the .edmx, but it doesn't generate the code required to get the foreign keys and cardinality correct. This means that the code will not work out-of-the-box, ...

That is not true. Once you set up EDMX correctly it will create exactly entities you want.

Does anyone know of a way to load an .edmx into the DbModelBuilder

That way is DbContext T4 generator!

Anyway there is one more tool you can check: EF Power Tools CTP1. This tool can create code first mapping from existing database.

Of course every tool creates model which is 1:1 mapping to the database. If you want anything more you must modify the model or mapping manually!

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • You say that the EDMX can produce almost anything, but as far as I understand it, the EDMX editor only has 2 Code Generation Strategies: Default and None - and to my knowlegde, Default only generates persistence-aware entities? Also, you say "That way is DbContext T4 generator", but I only get the plain C# equivalents of the existing tables, and my DbContext doens't seem to know or understand the foreign key relations that the database has - am I doing something wrong? – Leon Bouquiet Jul 13 '11 at 20:11
  • Yes you are wrong. You should really go through some tutorials. DbContext T4 Generator will create what is defined in EDMX but you can change that definition (not always as you want but that is global limitation in EF) - as I wrote you always start with 1:1 mapping. There is also POCO generator which is similar to DbContext Generator but it usese ObjectContext API instead. Relations are represented by navigation properties. You can turn on foreign key generation in import wizard. But didn't you want persistence ignorant objects? How foreign keys belong to object world? – Ladislav Mrnka Jul 13 '11 at 20:16
  • Yes I know that the function of the .edmx is to translate between the 'SQL' and the object world, and I know you can tweak the mapping between them to allow for inheritance etc. But the build tool associated with it can only create EntityObject-based code or no code. If you want POCO's, the only way is to have T4 templates process the edmx, right? What I meant with "doesn't understand foreign keys" is that, when I navigate a relation in code (i.e. load all OrderDetails for an Order), it looks for the wrong (a non-existent) foreign key column in my database, ...why? – Leon Bouquiet Jul 13 '11 at 20:26
  • Yes T4 template is alternative to default code generation. The problem with your relation is either: bad data, bad mapping (but default does it correctly) or problem with lazy / eager loading. – Ladislav Mrnka Jul 13 '11 at 20:32
1

Apparently, there are two ways you can use the generated code from the "ADO.NET DbContext Generator", depending on which type of connection string you use.

If you use an entity connection string, i.e.:

<connectionStrings>
  <add name="MyDBEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.;Initial Catalog=MyDB;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

the DbContext will be filled with all the metadata (column mappings, foreign key relations, etc.) from the .edmx. Also, the DbContext's OnModelCreating isn't executed. This is Database First using POCO's, and this is what I wanted to achieve.

What I did wrong was that I used a regular SQL connection string to pass into the DbContext. This causes a totally different type of behaviour: because the DbContext is now empty, it will try to explore all Entity classes and use conventions to generate a database schema for this. Now the OnModelCreating is called, expecting you to tweak this mapping and then generate a database from this.

In short, the solution was to use an entity connection string rather than a SQL connection string.

Leon Bouquiet
  • 4,159
  • 3
  • 25
  • 36
0

Read about the T4 POCO generation templates:

Those T4 code generation templates allow you to use

  • database-first approach with EDMX model file
  • but: generate simple POCO (plain-old CLR objects) which have no inheritance from any EF specific class - they're just absolutely plain CLR classes.....

This gives you the best of both worlds - a nice EDMX model and persistence-ignorant POCO classes.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459