I am using the EntityFramework POCO adapter and since there are limitations to what microsoft gives access to with regards to the meta data, i am manually extracting the information i need out of the xml. The only problem is i want to get the ssdl, msl, csdl file names to load without having to directly check for the connection string node in app.config.
In short where in the ObjectContext/EntityConnection can i get access to these file names?
Worst case scenario i need to get the connection name from the EntityConnection object then load this from app.config and parse the string itself and extract the filenames myself. (But i obviously don't want to do that).
Thanks
I can think of two ways to use reflection here:
Dig into the EntityConnection. The connection string should be in there somewhere as a private variable.
The EDM metadata files are embedded in the assembly as resources by default. You should be able to reflect the assembly that contains the EDM and pull the files out directly. Use Reflector on your assembly that contains your EDM and you should see the embedded msl, ssdl, an csdl.
I think option 2 is more robust overall.
Have you looked at the ObjectContext.MetadataWorkspace? It's not the easiest library to work with, but I was able to get all of the information that I needed.
Julia Lerman has a good chapter on the subject in her EF book.
Related
I just want to know how Entity Framework internally works to reveal properties and their types in runtime, particularly in case of Code-First approach, where there won't be system generated code. Can some body give some heads up? I don't think System.Reflection was being used implicitly?
Code first was first presented to developers as part of the EF Feature
CTP1 in June 2009 with the name “code only.” The basic premise behind
this variation of using the EF was that developers simply want to
define their domain classes and not bother with a physical model.
However, the EF runtime depends on that model’s XML to coerce queries
against the model into database queries and then the query results
from the database back into objects that are described by the model.
Without that metadata, the EF can’t do its job. But the metadata does
not need to be in a physical file. The EF reads those XML files once
during the application process, creates strongly typed metadata
objects based on that XML, and then does all of that interaction with
the in-memory XML.
Code first creates in-memory metadata objects, too. But instead of
creating it by reading XML files, it infers the metadata from the
domain classes (see Figure 1). It uses convention to do this and then
provides a means by which you can add additional configurations to
further refine the model.
ModelBuilder will now take this additional information into account as
it’s creating the in-memory model and working out the database schema.
By Julie Lerman
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.
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!
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="Data Source=.;Initial Catalog=MyDB;Integrated Security=True;MultipleActiveResultSets=True"" 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.
Read about the T4 POCO generation templates:
Walkthrough: POCO Template for the Entity Framework
POCO Template Code Generation Options
Using the POCO T4 Code Generation Template for Entity Data Models (video screencast with Julie Lerman)
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.
Our company is in the middle of evaluating a couple of different ORMs and we are currently looking at the EF4 side of things.
I have a small question that I hope someone here can answer...
In our generated EntityDataModel.Designer.cs file all our Entity classes (and the properties within them) have a ///summary with the sentence "No Metadata Documentation available".
Is there any way to have these picked up from the Description Property on the columns from SQL Server?
I can see there is a documentation property within the edmx file but they are all blank.
Obviously its not a deal breaker in our decision - but it would be nice.
Thanks for any advice
Aaron.
Yes, documentation properties are blank in EDMX because you must fill them yourselves. EF doesn't load columns descriptions defined in SQL Server.
These columns descriptions are stored in sys.extended_properties and have MS_Description as a name. Theoretically you can modify T4 template (EFv4) to load descriptions for columns and create comments but it would be a lot of work to do. You will have to:
for each scalar property you will have to search metadata to get column and table name and query DB to get a description
That is a lot of work and having T4 template opening connection to database is very uncommon.
I want to generate Entity Framework 4.0 classes from a (legacy) database from a command line, but I have 2 transformations I want:
Tables/columns are lowerCamelCase and I want my classes/members to be UpperCamelCase.
I want to suffix my classes with "Dto".
Any idea how this might be accomplished? I'm a total newbie to EF, but I have a decent understanding of Linq to Sql and was able to accomplish the same task by doing: sqlmetal -> dbml -> xml mapping file and .cs file.
The EDMX is also XML. If you're comfortable with XML transformations, just change the CSDL section of the file per your renaming rules. Then do a full build on your app and the code should be regenerated. To do this from the command line, use EdmGen, which comes with the framework. The free EdmGen2 utility is worth a look; it may already do some of what you need.
My concept is to have a logging/audit edmx file with corresponding mapped types defined in one project. This edmx has concepts and classes like AuditTrail and PropertyChange
A second edmx for the actual application models, domain if you will, with classes like Product, Category, and Order.
What I want to do is "scoop up" the first auditing edmx file into the second domain edmx. The schema information is 100% the same, the database has tables from both.
What I want to have happen is that these two edmx files are combined in such a way that I can use a transaction to save data such as both are dependent on each other finishing. My audit information can't save without my domain information and vice versa.
I've been goggling around and this seems possible I'm just missing some implementation detail thats not bringing this together.
This should be as simple as pointing the domain edxm and objectcontext connection string to the auditing edmx's csdl, ssdl, and msl files? The goal would be to load all of the MetaData information inside a single instance of an ObjectContext so I can wrap a call to both with a transaction.
This is what I have in my connection string for the web app/domain part of this application:
connectionString="metadata=res://*/Models.CfarModels.csdl|
res://*/Models.CfarModels.ssdl|
res://*/Models.CfarModels.msl|
W:\map\AuditModels.csdl|
W:\map\AuditModels.ssdl|
W:\map\AuditModels.msl;
Am I on the right track here is is this impossible?
While it is possible to load multiple CSDL files into one (Entity)Connection, it is not possible to load multiple MSL or SSDL files, because these are completely self-contained.
Back to the CSDL, there is a rarely used <using> element in CSDL. Which might give the impression that it is similar to a Reference in .NET, but actually it is more like a Merge.
I.e. one CSDL in another actually modifies both, merging them together, and potentially invalidates MSL's and SSDL's, by making them incomplete.
So back to your scenario:
You could in theory have 2 CSDLs:
1) To describe the Audit types
2) That uses (1) & defines the Domain Types and defines EntitySets and AssociationSets for both kinds of types.
You would then have one mapping file to map (2) and a storage model file too.
Which would leave you with something like this:
"metadata=res://*/Models.CfarModels.csdl|
res://*/Models.CfarModels.ssdl|
res://*/Models.CfarModels.msl|
W:\map\AuditModel.csdl;
Personally though I don't think you gain enough from this separation to make it worthwhile, most of the metadata is in the extents, the mapping and the storage model anyway, so type re-use while nice is only about 20% of the work anyway.
All you can really re-use is the audit type definitions, but that probably isn't worth the effort.
Hope this helps
Alex James
Microsoft.