Entity Framework 4.1 Complex Type reuse in different models - entity-framework

Here is the senario for which I could not find anything useful. Maybe Im the first person thinking of doing it this way:
Approach: Database First
Database: SQL Server 2008 R2
Project : DLL (Data Access)
I have a data access library which encapsulates all the access to database as well as the biz functionality. The database has many tables and all the tables have the following 2 columns:
last_updated_on: smalldatetime
last_updated_by: nvarchar(50)
The project contains several models (or edmx files) which contain only related entities which are mapped to the tables they represent. Since each of the table contain the columns for last_updated_* I created a complex type in one of the models that is as follows:
Complex Type: History
By (string: last_updated_by)
On (DateTime: last_updated_on)
The problem is that it can only be used in the model in which I defined it.
A) If I try to use it in other model it does not show it in the designer
B) If i define it in the other models I get error History already defined
Is there any solution so that the History complex type, defined in one model can be reused by other models?

I was trying to do almost the exact same thing (my DB fields are "created", "creatorId", "modified", and "modifierId", wrapped up into a complex type RecordHistory) and ran into this question before finding an answer...
http://msdn.microsoft.com/en-us/data/jj680147#Mapping outlines the solution, but since it's fairly simple I'll cover the basics here too:
First create the complex type as you did (select the fields in the .edmx Designer, right click, select "Refactor into New Complex Type")
In the .edmx Designer (NOT the Model Browser) right click on another table/entity that has the same common columns and select Add -> Complex Property
The new property will be assigned a complex type automatically. If you have more than 1 complex type, edit the new property's properties and set the Type appropriately
Right-click on the table/entity again (in either the Model Browser or Designer) and select Table Mapping
Update the Value/Property column for each of your common fields (changing them, in my case, from "modified : DateTime" to "history.modified : DateTime")
Delete the old common fields from your entity, leaving just the complex type in their place

Related

Entity Framework 'Update Model from Database' recreating associations between base and sub classes

I am trying to implement a number of base/sub classes using Entity Framework, database first. Following some online tutorials, I have decided to attempt TPT inheritance.
On the database, I have a base class table 'Location', and two sub class tables: 'StreetAddress' and 'RuralRouteAddress'. I have defined a foreign key constraint between the sub class tables and the base class table on their primary keys. 'Location's Primary Key is an auto-increment column, and the two sub class tables' primary keys are not auto-increment.
In Entity Framework, I defined the 'Base Type' of the two sub classes as 'Location'. I then deleted the associations (and their corresponding navigation properties) from the model. I also deleted the ID column mappings from the sub classes, as ID is now inherited from the 'Location' base class.
This seems to have worked. I haven't tried updating/inserting, but querying returns the data with proper inheritance in place.
My problem is that, whenever I 'Update Model from Database', he inheritance association lines stay, but the FK associations between the base class and the sub classes are brought back... . I then have to delete them, and realign the association lines on my diagram (I'm a bit picky about the layout of the model diagram).
This isn't so bad, but the project that I would like to use TPT inheritance in has a lot of inheritance. Having to delete a ton of associations and reorganize my entire diagram every time I update the model is not very appealing.
Did I do something wrong when I implemented inheritance? Is there a way to ignore/exclude certain associations from being created when updating the model?
The relationships you define in the database will always reappear when you update the model from the database. This is by design. If you want to have classes in the model that have a different relationship structure, try creating a complex model from a stored procedure that selects all the columns (or all the columns you want) from the base table. Import that procedure and in the Function Imports, edit the return type by creating a new complex type, or even just renaming the result that EF automatically creates. Then add your associations on that type, and use it as the base type for your inherited classes.
The good part of this is that you can adjust the type structure to match any table changes by editing the stored procedure, then using "Get Column Information" and "Update" to bring the complex type into line. It won't overwrite your associations because they aren't defined in the database, but it is almost as straightforward as using TPT.
Joey

Select Specific Columns from Database using EF Code First

We have a customer very large table with over 500 columns (i know someone does that!)
Many of these columns are in fact foreign keys to other tables.
We also have the requirement to eager load some of the related tables.
Is there any way in Linq to SQL or Dynamic Linq to specify what columns to be retrieved from the database?
I am looking for a linq statement that actually HAS this effect on the generated SQL Statement:
SELECT Id, Name FROM Book
When we run the reguar query generated by EF, SQL Server throws an error that you have reached the maximum number of columns that can be selected within a query!!!
Any help is much appreciated!
Yes exactly this is the case, the table has 500 columns and is self referencing our tool automatically eager loads the first level relations and this hits the SQL limit on number of columns that can be queried.
I was hoping that I can set to only load limited columns of the related Entities such as Id and Name (which is used in the UI to view the record to user)
I guess the other option is to control what FK columns should be eager loaded. However this still remains problem for tables that has a binary or ntext column which you may not want to load all the times.
Is there a way to hook multiple models (Entities) to the same table in Code First? We tried doing this I think the effort failed miserably.
Yes you can return only subset of columns by using projection:
var result = from x in context.LargeTable
select new { x.Id, x.Name };
The problem: projection and eager loading doesn't work together. Once you start using projections or custom joins you are changing shape of the query and you cannot use Include (EF will ignore it). The only way in such scenario is to manually include relations in the projected result set:
var result = from x in context.LargeTable
select new {
Id = x.Id,
Name = x.Name,
// You can filter or project relations as well
RelatedEnitites = x.SomeRelation.Where(...)
};
You can also project to specific type BUT that specific type must not be mapped (so you cannot for example project to LargeTable entity from my sample). Projection to the mapped entity can be done only on materialized data in Linq-to-objects.
Edit:
There is probably some misunderstanding how EF works. EF works on top of entities - entity is what you have mapped. If you map 500 columns to the entity, EF simply use that entity as you defined it. It means that querying loads entity and persisting saves entity.
Why it works this way? Entity is considered as atomic data structure and its data can be loaded and tracked only once - that is a key feature for ability to correctly persist changes back to the database. It doesn't mean that you should not load only subset of columns if you need it but you should understand that loading subset of columns doesn't define your original entity - it is considered as arbitrary view on data in your entity. This view is not tracked and cannot be persisted back to database without some additional effort (simply because EF doesn't hold any information about the origin of the projection).
EF also place some additional constraints on the ability to map the entity
Each table can be normally mapped only once. Why? Again because mapping table multiple times to different entities can break ability to correctly persist those entities - for example if any non-key column is mapped twice and you load instance of both entities mapped to the same record, which of mapped values will you use during saving changes?
There are two exceptions which allow you mapping table multiple times
Table per hierarchy inheritance - this is a mapping where table can contains records from multiple entity types defined in inheritance hierarchy. Columns mapped to the base entity in the hierarchy must be shared by all entities. Every derived entity type can have its own columns mapped to its specific properties (other entity types have these columns always empty). It is not possible to share column for derived properties among multiple entities. There must also be one additional column called discriminator telling EF which entity type is stored in the record - this columns cannot be mapped as property because it is already mapped as type discriminator.
Table splitting - this is direct solution for the single table mapping limitation. It allows you to split table into multiple entities with some constraints:
There must be one-to-one relation between entities. You have one central entity used to load the core data and all other entities are accessible through navigation properties from this entity. Eager loading, lazy loading and explicit loading works normally.
The relation is real 1-1 so both parts or relation must always exists.
Entities must not share any property except the key - this constraint will solve the initial problem because each modifiable property is mapped only once
Every entity from the split table must have a mapped key property
Insertion requires whole object graph to be populated because other entities can contain mapped required columns
Linq-to-Sql also contains ability to mark a column as lazy loaded but this feature is currently not available in EF - you can vote for that feature.
It leads to your options for optimization
Use projections to get read-only "view" for entity
You can do that in Linq query as I showed in the previous part of this answer
You can create database view and map it as a new "entity"
In EDMX you can also use Defining query or Query view to encapsulate either SQL or ESQL projection in your mapping
Use table splitting
EDMX allows you splitting table to many entities without any problem
Code first allows you splitting table as well but there are some problems when you split table to more than two entities (I think it requires each entity type to have navigation property to all other entity types from split table - that makes it really hard to use).
Create stored procedures that query the number of columns needed and then call the stored procs from code.

Entity framework: Database first/Code first hybrid

I am trying to create a custom Entity Framework (4.2) entity that would be mapped to my database like it would be done in a Code first approach.
The issue is that my entity framework data model is using Database first.
How can I add my custom entity to entity framework's context?
If by the Database first you mean that you already have EDMX created from exiting database you simply cannot use code first. You must create table and update model (EDMX) from the database to include it in EDMX.
Edit based on comment:
I want to create a BriefUser entity that would basically be a lighter
version of User but it would have properties retrieved from User's
foreign keys.
Well this is possible. You can either create BriefUser as common class and use projection in query.
var breifUser = (from x in context.Users
where ...
select new BriefUser
{
// Fill BreifUser's properties here
}).FirstOrDefault();
You can even refactor former code to reusable extension method:
public static IQueryable<BriefUser> ProjectUser(this IQueryable<User> query)
{
return query.Select(x => new BreifUser()
{ // Fill BreifUser's properties here });
}
and use it like:
var briefUser = context.Users.ProjectUser().FirstOrDefault(...);
It is also possible to define your new class as "entity view". The first problem is that each table can be mapped to only one entity (except some advanced concepts like inheritance or splitting) so you cannot define your BriefUser as a new entity type because mapping both User and BriefUser to UserTbl would violate this rule. You must use special construct called QueryView.
QueryView is view in mapping level. It allows you to create new mapped type which is projection of existing mapped entities defined directly in EDMX's MSL part. The projection is defined as custom Entity SQL query. The problem is that QueryView has limitations:
It doesn't offer all Entity SQL features - for example it doesn't support aggregations (which I consider as really missing feature). Without aggregations you for example cannot create a new type which will contain property counting some related entities.
It is not supported in designer. You must edit your EDMX as XML to define QueryView and you must write Entity SQL query yourselves.
Resulting type is a "view" and it is read-only.
I want to keep the EDMX file, but also be able to add an entity
(BriefUser) to EF's context.
This is not possible. Your BreifUser is only projection / view and EF is not able to track changes back to originating tables so you cannot add BreifUser to context and persist it. In case of QueryView you can achieve it if you define custom stored procedures which will no how to decompose BreifUser and modify all related tables. These stored procedures must be imported to the EDMX and mapped to data modification operations of the view entity. Btw. same will happen if you map your entity to the database view because EF takes all views as read-only.

Entity Framework STEs and many-To-many associations

I'm fairly new to EF and STE's, but I've stumbled on a painful point recently, and I'm wondering how others are dealing with it...
For example, suppose I have two STE's: Employee and Project. It's a many-to-many relationship. Each entity has a navigation property to the other (i.e. Employee.Projects and Project.Employees).
In my UI, a user can create/edit an Employee and associate it with multiple Projects. When the user is ready to commit, a list of Employees is passed to the server to save. However, if an Employee is not added to the "save list" (i.e. it was discarded), but an association was made to one or more Projects, the ApplyChanges extension method is able to "resurrect" the Employee object because it was "connected" to the object graph via the association to a Project.
My "save" code looks something like this:
public void UpdateEmployees(IEnumerable<Entities.Employee> employees)
{
using (var context = new EmployeeModelContainer(_connectionString))
{
foreach (var employee in employees)
{
context.Employees.ApplyChanges(employee);
}
context.SaveChanges();
}
}
I've been able to avoid this issue to now on other object graphs by using FKs to manipulate associations as described here: http://blogs.msdn.com/b/diego/archive/2010/10/06/self-tracking-entities-applychanges-and-duplicate-entities.aspx
How does one handle this when a many-to-many association and navigation properties are involved?
Thanks.
While this answer's a year late, perhaps it will be of some help to you (or at least someone else)
The simple answer is this: do not allow Entity Framework to infer m:m relationships. Unfortunately, I'm not aware of a way of preventing this, only how to deal with it after the fact.
By default, if I have a schema like this:
Employee EmployeeProject Project
----------- --------------- ----------
EmployeeId ---> EmployeeId |--> ProjectId
Name ProjectId ----- Name
... ...
Entity Framework will see that my EmployeeProject table is a simple association table with no additional information (for example, I might add a Date field to indicate when they joined a project). In such cases, it maps the relationship over an association rather than an entity. This makes for pretty code, as it helps to mitigate the oft-referenced impedence mismatch between a RDBMS and object-oriented development. After all, if I were just modeling these as objects, I'd code it the same way, right?
As you've seen, however, this can cause problems (even without using STE's, which cause even MORE problems with m:m relationships). So, what's a dev to do?
(The following assumes a DATABASE FIRST approach. Anything else and you're on your own)
You have two choices:
Add another column to your association table so that EF thinks it has more meaning and can't map it to an association. This is, of course, bad design, as you presumably don't need that column (otherwise you'd already have it) and you're only adding it because of the particular peculiarities of the ORM you've chosen. So don't.
After your context has been generated, map the association table yourself to an entity that you create by hand. To do that, follow the following steps:
Select the association in the designer and delete it. The designer will inform you that the table in question is no longer mapped and will ask you if you want to remove it from the model. Answer NO
Create a new entity (don't have it create a key property) and map it to your association table in the Mapping Details window
Right-click on your new entity and add an association
Correct the entity and multiplicity values (left side should have your association entity with a multiplicity of *, right should have the other entity with a multiplicity of 1)
Check the option that says "Add foreign key properties to the Entity"
Repeat for the other entity in the association
Fix the property names on the association entity (if desired...not strictly necessary but they're almost certainly wrong) and map them to the appropriate columns in the Mapping Details window
Select all of the scalar properties on your association entity and set them as EntityKey=True in the Properties window
Done!

Entity framework 4 model first using money value object

I want to use a Money value object in my application. I have found several examples of a Money datatype. But I can't figure out how to use them with EF4. I would like to store each amount as a Decimal/CurrencyCode pair (where currencycode is a string - "USD", "SEK", etc) in the database. I tried creating a complexType but I couldn't get that to work. Is this possible?
It should be definitely possible. Your complex type is just pair of decimal and string property. It is exactly what complex type are used for. Depending on your approach you must do:
Database first:
You will define your database first. Your table will contain money and varchar columns representing your new type. When you update your EDMX model from database it will include it as scalar properties to your entity. You must remove those properties. Then go to model browser and create new complex type. Return back to entity and add complex property of your new complex type. And at the end you must go to entity mapping and map your complex type to those database columns.
Here is basic tutorial from MSDN but from unknown reason they didn't include such elementary details like screenshots. Here is some video from channel9.
Model first:
This is similar to database first but you don't have to deal with database creation and mapping. It will be generated for you.
Code first (EF 4.1):
You must create separate class for your complex type and use it as property in your entity. You should not need to map it by default - mapping should be infered. If it doesn't work you can map complext type either by using ComplextTypeAttribute annotation or by defining mapping in DbModelBuilder.
I can further extend approach you need to use if you provide more details.