Compose queries across Entity Data Models - entity-framework

Is there a way to compose queries from 2 different entity models if the models are hitting the same underlying database.
The scenario I have is this:
I have a framework that uses EF for data access.(EDM 1)
I have a client application that uses services of the framework and also uses EF for it's own data access.(EDM2)
There are situations where I need to compose queries and join on entities that span the 2 EDMs.
Is there a way to do this without getting the data in memory from the first EDM and then apply additional predicates/joins in memory from the entities of the 2nd EDM?
I hope I'm articulating this the right way
EDIT
#Ladislav Mrnka:
The first EDM is the data access layer for a reusable framework.
It doesn't make sense to couple the EF generated entities from this EDM with
those of the consuming client
It defeats reusabilty of the API if I did this and I'd have to carry around additonal bloat
(EF metadata and DB tables of the client) everytime I wanted to redeploy the framework.
Also this would make managing the model in the designer unwieldy.
I'm currently using what you mention n item 7 as the solutuon and the performance is abysmal
due to the fact that I have to end up returning more data(i.e. entities) than needed from framework using
EDM1 and then filter out the ones not needed based on predicates/conditions based on value of
properties from entities in the second EDM. End result is a huge performance degradation and an unhappy DBA.
For this reason I ended up pushing the logic needed to retrieve the entities
to a SPROC in which I can access the tables that both EDMs use and apply the predicates needed
and have the entire query run in the DB as opposed to bringing the data in memory
and then filter out unnecessary ones.Downside is that I can't use LINQ
Item 8 that you mention sounds interesting but from what it sounds like I doubt that
you get strong typing at design time, or do you?
Can you upload your code sample someplace so that I can try it out?

Important edit
There is no build in support for achieving this with two ObjectContext types. Your query must always be executed against single ObjectContext.
Probably the best way to go: This was interesting enough for me to try it myself. I started with very simple idea. Two EDMX files (used with POCO T4 generators), each containing single entity. I take metadata description from second connection string and added it to first connection string. I used ObjectContext and ObjectSet directly. By doing this I was able to query and modify both entities from single ObjectContext instance. I also tryed to create query joining entities from both models and it worked.
This obviously works only if both EDMX map to the same database (same db connection string).
The important part is connections string:
<configuration>
<connectionStrings>
<add name="TestEntities" connectionString="metadata=res://*/FirstModel.csdl|res://*/FirstModel.ssdl|res://*/FirstModel.msl|res://*/SecondModel.csdl|res://*/SecondModel.ssdl|res://*/SecondModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.;Initial Catalog=Test;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
This connection string contains metadata from two models - FirstModel.edmx and SecondModel.edmx.
Another problem is to force EF to use mapping from both these files. Each EDMX file must define unique container for SSDL and CSDL. ObjectContext offers property called DefaultContainerName. This property can be set directly or through some constructor overloads. Once you set this property you bind your ObjectContext instance to single EDMX - for this scenario you must not set this property. Omitting DefaultContainerName can have some consequences because some features and declarations can stop working (you will get runtime errors). You should not have problems with POCO unless you want to use some advanced features. You will most probably have proplems if you are using Entity objects (heavy EF entities. All methods using entity sets defined as strings are dependent on container. Due to this I suggest using such configuration only when necessary - for cross models queries.
Last problem is generating entities and "strongly typed" derived ObjectContext. The way to go is modify T4 template so that one template reads data from multiple EDMX files and generates context end entities for all of them - I already doing this in my project and it works. Default T4 implementation doesn't follow needed approach described in previous paragraph. Derived ObjectContext from default T4 implementation is dependent on single EDMX and entity container.
This part has been written before previous edit.
I'm leaving the rest of information just because some of them can be useful in other scenarios including work with multiple databases.
ORM like entity framework operates on top of mapping between object world and database world. In EF the object world is described by CSDL, database world is described as SSDL and mapping between them is described as MSL (all are just XML with well known schema). At design time these descriptions are part of model stored in EDMX file. During compilation these descriptions are extracted from EDMX and by default included as resource files to compiled assembly.
When you create instance of ObjectContext it receives connections string which contains reference to CSDL, SSDL and MSL resource files. SSDL or MSL do not specify include element to add information from other files. CSDL offers Using element which will allow you reusing existing mapping but this feature is not supported by designer. ConnectionString is used to initialize EntityConnection instance which is in turn used to initialize ObjectContext's MetadataWorkspace (runtime mapping information). Also ObjectContext doesn't provide any functionality of nesting multiple contexts into hiearchy. Connection string can't contain reference to multiple instances of these files. Edit: It can. I just tested it. See the initial paragraphs.
When you run Linq or ESQL query on the instance of ObjectContext it usese MSL to map your entities or POCO classes (defined by CSDL) into DB query (defined by SSDL description of database tables). If it doesn't have this information it will not work (and it can't have that information if it is stored in separate EDMX).
So how to solve this problem? There are several ways:
Always consider: Merge your mapping into one file (if multiple files are used for same database). That is supposed way to use EF and as you mentioned you are querying same DB so two EF models are not needed.
Duplicate entity description in second model. If you use EF4 and POCO you can map same descriptions from multiple models into one POCO class definition. I don't like this solution but sometimes it can help.
Define DB View or Stored procedure containing your query (or core of your query) and map it in one model to new entity.
Use DefiningQuery in one model (you will probably need 3rd one if you use Update from database feature) and map it to new entity. DefiningQuery is custom SQL query defined in SSDL instead of table or view description.
Use Function with custom CommandText specifying DB query. It is similar to using DefiningQuery and it has the same limitation. You must manually (in EDMX) map the result of the function into new complex type (another difference to DefiningQuery which is mapped to new entity).
Define new type for result of the query (properties of the type must have same names as returned columns in query) and use ObjectContext's ExecuteStoreQuery (only in EF4).
Divide query into two parts each executed separately on its own context and use linq-to-objects to get result. I don't like this solution.
This one is only high level idea - I didn't try it and I don't know if it works. As described above runtime mapping is dependent on the content of MetadataWorkspace instance which is filled from EntityConnection. EntityConnection also provides constructor which receives MetadataWorkspace instance directly. So generally if it would be possible to fill MetadataWorkspace from multiple EDMX you will not need multiple ObjectContext instances but your mapping would be still separated into two EDMXs. This would hopefully allow you writing custom Linq queries on top of two mapping files). Edit: It should be possible because it is exactly what EF is doing if you define multiple mappings in connection string.
Use CSDL Using feature for breaking the model into multiple reused parts.

Related

How entity framework reveals properties and types of a code first entity in runtime?

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

Sharing entity types across multiple edmx files

We are using Entity Framework 4 with the POCO Entity Generator. Until now we've just had one .edmx file but we're running into performance problems due to the current size of it (well over 100 entities).
I understand we should be looking to break this into a series of .edmx files which is fine with one exception. We would want to somehow share certain entity types across two or more of these contexts. For example a User class is associated with numerous otherwise unrelated entities throughout our model.
So is it possible to have, say, a security model with its own .edmx and namespace for generated POCOs, but use it in another .emdx? If not I'm concerned we'll have multiple classes modelling the same database table which will need to be updated in sync with the database. I'd say that would be unworkable. (We're using database-first).
Obviously if I'm barking up the wrong tree do let me know!
In theory you can have single POCO class used with multiple EDMX mappings because the mapping and class must match only in the name and name/types of properties. In practice this has some limitations. Just few I can think about:
You cannot use automatic code generators with this approach unless you modify generator for every EDMX and make sure that every entity will be generated by just single generator from single EDMX. This directly points to second limitation.
Entity must be exactly same in every EDMX. Including navigation properties. If it is not you will not be able to generate it at all without building your own code generation solution. What is worse if dynamic proxies demand that class with unique name is mapped only once. If you have two or more different mappings for the same class you will not be able to use dynamic proxies (lazy loading, dynamic change tracking) with only single mapping per application run.

POCO entity without some fields (Free modeling of the entities)

I understand that, when working with POCO entities, you should work against your model (POCO Entities). Also I supose that part of the benefits of programming against models like those should provide benefits like defining classes that don't match exactly what you see in the db.
However, there are simple operations that I don't know how to do and that I assume they should be possible. For example, in some scenarios it can be useful to change the name of one column (atribute in the entity). Also I would like to know if it's possible to generate POCO models that only represents some fields of the table that supports the object in the db.
Is there any documentation about this kind of operations?
¡Thanks a lot!
POCO entity is just mapped class. The model in your question means mapping. The point of mapping is to define map between class and database table including mapping between properties and columns. So you can have different property and column names as long as it is correctly configured in mapping.
So if you are using EDMX file (designer) for generating the mapping you can simply change the name of property or entity and it will be reflected in your generated POCO entity. Also EDMX file will correctly update mapping. If you are using code first you must manually define mapping either through data annotations or through fluent API.
Entity should represent single data structure persisted to the database. Because of this each table can be mapped only once. Moreover EDMX designer demands that each non-nullable column without default value must be mapped to the entity. POCO generator is not tool for generating your different data views. What you are looking for is called projection. There are ways how to include mapped projections in EDMX file (DefiningQuery and QueryView) but both requires manual modifications of EDMX file and the first one also requires manual maintenance of EDMX file.
If you need to remove some properties from entity just to improve some query or because you don't need all data for some operation you can always use projection to anonymous or custom class directly in the query.
var query = from x in context.XEntities
select new XView
{
A = x.A,
B = x.B
};
POCO generator is only tool for generating classes for mapped entities and projections not for generating all data related classes you will ever need.

Defining business objects in Entity Framework

Trying to understand Entity Framework. My approach is database first. However I would like to define other entites in the model that is closer to my business objects. I guess I could write queries in the db and include them in the model. But I would also like to define entirely new entities in the model though they would be based on underlying tables in the db. How do I do that - does anyone know a tutorial?
Regards
Bjørn
db Oldtimer, EF Newbie
Database first means that you have existing database and you can either create model by updating from database or manually. You can use wizard to create initial model and modify it manually to define new entities but you must not use update from database any more or some of your changes will be deleted. Also your custom modifications must follow EF mapping rules (for example it is not directly possible to map multiple entities to the same table except some more advanced mapping scenarios like splitting and inheritance) and some of them (custom queries) must be done directly in EDMX source (XML) because designer doesn't support them - this requires more complex knowledge of EF mapping and it will be definitely hard for newbie.
You can check specification of that XML. For entities mapped to custom queries you will have to use DefiningQuery element in SSDL part of EDMX.

Load an .edmx into the DbModelBuilder

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.