EF relationships when adding to database - entity-framework

I have a question about relationships in Entity Framework when adding to database.
I have the following layers
Web app
Service layer
Repository
Data layer
Lets say i have these entities
Course
Department
These entities reference each other.
In my service layer I get the course entity and the department entity.
Then I do something like:
Course.Department = department;
Unitofwork.CourseSet.Add(Course);
Unitofwork.SaveChanges();
My question is then:
Do I also need to add the department entity to the context?
Because even if I dont add the department to the DepartmentSet it is still beeing added to the database.
Is there some kind og rule about when to add to the context and when its not necesary
Hope someone can help

You don't need to add related entities separately since EF is able to detect that automatically.
Also, even if you do add it separately, it will have no effect since the related entity is (internally) already attached to the Context and its state is already set to 'Added'.
The 'rule' you're looking for is very simple: if it's not part of the 'root' entity, you'll have to add it separately.
P.S: This is all true for Insert/Add scenario. Update/Edit scenario (from detached entity) is more complicated and changes to related entities usually aren't detected.

Related

What is included in DbContext model?

Description:
I've tried to separate certain domain segments into different DbContexts.
Each has several DbSets, but there are some DbSets that are shared, for example the UserProfile.
The reason for this separation is the speed at which the model is generated and the simplicity (less sets in an object, helps with intellisense).
However, I am not sure about what exactly belongs to the model that is generated.
Q1: Is every entity that is transitionally connected with the entities, for which a DbSet exists in a DbContext, included in the model?
Q2: If so, would that mean that performance-wise it serves no purpose to separate the domain into different contexts, since everything that is connected ends up in the model anyway, no matter which DbSets are stated in the DbContext?
Where can I find more information on how the model is generated? I've read a book on EntityFramework and CodeFirst and couldn't find that specific information...
Answering your first question: yes, all relations are modeled including the entities on both sides, so every entity that's connected by a navigation property to an included entity will also be included in the model regardless if there's a DbSet for it or not.
Entity Framework doesn't force you to create DbSets for all entities. This can be handy if you want to "restrict" child entities to only be accessible through their parents.
Regarding your second question: separating your contexts might still improve performance, if not all entities belonging to one context are reachable via navigation properties of entities belonging to the other context. There could be an additional cost associated with explicitly including more DbSets in a context, too.
You could read (some parts of) the Entity Framework source code, it's open-source and available on CodePlex to learn more about how the model is built.

Entity Framework 5, Multiple Models, Same Entity

Ok, so I am new to entity framework...
I have an existing SQL database with some 500 tables in it, and we are in the process of considering a move from Linq->SQL to Entity Framework as our main data access layer. We also want to consider more of a domain driven design approach with separate data contexts managing key areas of the application ( i.e. Sales, Marketing, Jobs, Shipping etc. etc. ).
If we take a common entity such as "Customer", this appears in more than one model. I have two models in my sample app so far. Entity Framework is clever enough to create only one customer class ( we are using the default Poco T4 templates for class generation ), however when I try and run the project I get the following error "Multiple types with the name 'Customer' exist in the EdmItemCollection in different namespaces. Convention based mapping requires unique names without regard to namespace in the EdmItemCollection".
So am I right in thinking that Entity Framework does not allow "Customer" to exist in more than one model ? If I really want customer appearing in more than one model, do I have to start creating different versions of the customer class to deal with it ?
Apologies in advance if this is a dumb question, but I am relatively new to EF.
Thanks...
You said that you are creating DDD with bounded context. In bounded context, you create more than one context with one or more related entities in it. Why do you want to create more than one model with the same name?
Check the Julie Lerman's link for reference:
http://msdn.microsoft.com/en-us/magazine/jj883952.aspx
Sorry if I am out of context. But, in my experience in such a scenario, we have to create two different context such as "MarketingModelContext" and SalesModelContext. MarketingModelContext will have all the dbsets related to marketingmodel along with customer entity. In the same way, SalesModelContext will have all the dbsets related to SalesModel along with customer entity. In this way, you will be creating only one customer entity or POCO which can be used by two contexts independently. This is known as bounded contexts as Julie Lerman calls it. It will help you in separation of context, concerns and helps you with better performance as only required context(fewer entities) can be loaded. The above article will help you with this.
Hope I have answered your query.

WCF, Entity Framework 4.1 and Entity's State

I am developing an application which will expose WCF services. I am using Entity Framework 4.1 at the DAL. The problem is when I load some entity (let say a Customer that has Order which in turn has OrderDetail). After loading it I make some changes in Customer, Order and OrderDetail objects (some new orders are added and some existing orders are removed/updated) and send the object graph to WCF service to update it as following.
Customer oCustomer;
using(var context = new MyContext) //MyContext is dbContext
{
oCustomer = context.Include("Order.OrderDetail").Find(1);
}
oCustomer.Name ="blah blah";
Order oOrder1 = oCustomer.Order.Where(obj=>obj.Id == 2);
oOrder1.Description = "blah blah";
oOrder1.OrderDetail.Quantity = 10;
Order oOrder2 = new Order { ... } //properties of Order are set.
oCustomer.Order.Add(oOrder2);
oCustomer.Order.Remove(context.Order.Find(1));
ServiceClient client = new ServiceClient();
client.SaveCustomer(oCustomer);
Now when I receive the updated ObjectGraph of Customer at Server side I don't know which Order was removed and which was modified, since there is no changetracking now. How can I determine that which Order to Delete and Which Order to Modify? Is there any way to track the changes in my object graph in Entity Framework 4.1?
NOTE: Previously I used Self Tracking Entities which solved this problem but I had to get rid of STEs since my WCF service is gonna be used by Java Client apps as well. So, STEs are not an option for me.
I wonder if it makes any sense to answer your questions because it looks like you don't read answers.
You asked question about STEs and you got answers about their usability.
I added link where it was explicitly described that they are not for interoperable scenarios
Richard posted very good links about STEs and about custom change tracking - btw. it is exactly what you are looking for now
You probably didn't read those answers because you used STEs and after that you asked a question how to use STEs in Java client.
What surprise me even more you did duplicate of your own question about STE and EFv4.1
Can I use Self Tracking Entities and DBContext in Entity Framework 4.1?
Using STE entities in Entity Framework 4.1
Today you already get an answer for this question in another your question.
So what answer do you expect? Does it worth it to answer your questions if you don't read answers?
Answer:
There isn't STE template for DbContext and once you are not using STEs you must handle change tracking completely yourselves because EF doesn't help you. The easiest approach is described in your previous question - load the object graph again in the service and merge incoming graph to attached entities so that context can track changes. The more complex solution is described in the link #Richard provided in one of your former questions about STE - you must add some state property to each transferred entity and client must set them correctly and post them back to you so that you can manually set correct state for each entity once you attach them - this can be little bit complex in case some relations.
As far as know there is no way to track changes of a detached object graph aside from Self Tracking Entities (which you can't use as you say).
What I usually do to update a detached graph is to reload the original graph from the database, compare the original with the changed graph (hand-written code case by case) to see which entities have been added, modified and deleted, write the changes into the original and save the context.
An example to this procedure (for one parent and a child collection, for instance Customer and Order collection) is in the answers to this question: The relationship could not be changed because one or more of the foreign-key properties is non-nullable
It's unfortunately getting quite complex if you have to deal with a deeper hierarchy of entities. As far as I can see EF doesn't offer any kind of automatic merging of a changed graph into the original, only for the very simple case where an entity only has scalar and complex properties which have been changed. As soon as navigation properties are involved you have no support from EF anymore and you have to write the update logic yourself.

how can i know when a self-tracking entity has been changed?

I have been working with the Entity Framework + Self-Tracking entities, and came out with a problem:
Is there any way to determine when an entity has been changed??
For example: If you have an entity User with two fields: Name and Password, you can know if an User instance has been changed making:
<user>.ChangeTracker.State != ObjectState.Unchanged;
My problem is when the User has a Person, and the person has a field Email. I want that if the email field is changed, then the corresponding User is changed too.
I have been trying with methods such as: <user>.StartTrackingAll(); but this does not work with navigation properties (or maybe i am doing something wrong). Some help about this can be found here.
Remember that the Self tracking entities are autogenerated via T4 templates, so the clases can't be modified.
First when wanting to know if any entity in a so-called object graph has changed you can recurse through all entities contained in trackable collections or one-to-one navigation properties of a root entity (user in your case). This way you can know if a person inside the root entity has changed. This is actually how I check complex object graphs for any changes in any of the contained entities. But also for checking out if any of these entities have critical validation errors (so the user can't persist them yet).
Remember that the Self tracking entities are autogenerated via T4 templates, so the clases can't be modified.
Not true. First of all you can modify the T4 template to generate more (complex) code to achieve the things you want. And second, it generates partial classes which can easily be extended with custom (non-generated) code.
If you change the email in the Person instance only that instance is correctly marked as modified. That is absolutely correct behaviour. What do you expect? Do you expect that change to property in related entity will propagate changed state to relations? That would make STEs completely useless because any single change to entity graph would make all entities in the graph modified and each this modification causes additional roundtrip to the database.
If you want to set User as modified when you are changing email simply create some method or handle some event and call person.User.MarkAsModified()

Entity Framework Service Layer Update POCO

I am using the Service Layer --> Repository --> Entity Framework (Code-First) w/POCO objects approach, and I am having a hard time with updating entities.
I am using AutoMapper to map my Domain Objects to my View Models and that works good for getting the data, no how do I get that changes back into the database?
Using pure POCO objects, I would assume that there is no sort of change tracking, so I see my only option is to handle it myself. Do you just make sure that your View Models have the EXACT same properties as your Domain Objects? What if I just change a field or two on the View Model? Won't the rest of the fields on the Domain Object get overwritten in the database with default values?
With that said, what is the best approach?
Thanks!
Edit
So what I am stumbling on is this, lets take for example a simple Customer:
1) The Controller has a service, CustomerService, that calls the services GetCustmoerByID method.
2) The Service calls into the CustomerRepository and retrieves the Customer object.
3) Controller uses AutoMapper to map the Customer to the ViewModel.
4) Controller hands the model to the View. Everything is great!
Now in the view you do some modifications of the customer and post it back to the controller to persist the changes to the database.
I would assume at this point the object is detached. So should the model have the EXACT same properties as the Customer object? And do you have to make hidden fields for each item that you do not want to show, so they can persist back?
How do you handle saving the object back to the database? What happens if your view/model only deals with a couple of the fields on the object?
If you're using EF Code First, i.e: the DbContext API, then you still do have change tracking which is taken care of by your context class.
after making changes to your objects, all you have to do is call SaveChanges() on your context and that will persist the changes to your database.
EDIT:
Since you are creating a "copy" of the entity using AutoMapper, then it's no longer attached to your context.
I guess what you could do is something similar to what you would in ASP.NET MVC (with UpdateModel). You can get the original entity from your context, take your ViewModel (which may contain changed properties) and update the old entity, either manually (just modified properties), or using AutoMapper. And then persist the changes using context.SaveChanges().
Another solution would be to send the model entity as [part of] the ViewModel. This way, you'll have your entity attached to the container and change tracking will still work.
Hope this helps :)
You are absolutely right that with a detached object you are responsible for informing the context about changes in your detached entity.
The basic approach is just set the entity as modified. This works for scalar and complex properties but it doesn't work for navigation properties (except FK relations) - for further reading about problems with navigation properties check this answer (it is related to EFv4 and ObjectContext API but same problems are with DbContext API). The disadvantage of this approach is that all fields in DB will be modified. If you just want to modify single field you still have to correctly fill others or your database record will be corrupted.
There is a way to explicitly define which fields have changed. You will set the modified state per property instead of whole entity. It is little bit harder to solve this on generic approach but I tried to show some way for EFv4 and for EFv4.1.
I agree with #AbdouMoumen that it's much simpler to use the model entities at the view level. The service layer should provide an API to persist those entities in the data store (db). The service layer shouldn't dumbly duplicate the repository lawyer (ie: Save(entity) for every entity) but rather provide a high level save for an aggregate of entities. For instance, you could have a Save(order) in the service layer which results in updating more basic entities like inventory, customer, account.