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.
Related
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.
We're creating a WebAPI using Entity Framework in MVC 4. Our client wants to send complex objects containing related objects - both new and updated. The root object maybe new or existing one too. The client generates primary keys - we're using Guids for that. So on server we really can't tell that we got an existing object update or a new one. What would be the best way to handle this situation? We need some sort of add or update functionality and it's not yet clear to us how to proceed with Entity Framework for this.
EF doesn't have any build in support for discovering changes in detached object graph. You either have to include some field into every object describing if the object is new, not modified, updated or deleted (you will also need similar behavior to track changes in many-to-many relationships). If you don't use such field you have no other way than querying database and comparing current DB state with data received from client to find what has changed.
I'm using Entity Framework 4.1. I've implemented a base repository using lots of the examples online. My repository get methods take a bool parameter to decide whether to track the entities. Sometimes, I want to load an entity and track it, other times, for some entities, I simply want to read them and display them (i.e. in a graph). In this situation there is never a need to edit, so I don't want the overhead of tracking them. Also, graph entities are sent to a silverlight client, so the entities are disconnected from the context. Hence my Get methods can return a list of entities that are either tracked or not. This is achieved dynamically creating the query as follows:
DbQuery<E> query = Context.Set<E>();
// Track the entities in the context?
if (!trackEntities)
{
query = query.AsNoTracking();
}
However, I now want to enable the user to interact with the graph and edit it. This will not happen very often, so I still want to get some entities without tracking them but to have the ability to save them. To do this I simply attach them to the context and set the state as modified. Everything is working so far.
I am auditing any changes by overriding the SaveChanges method. As explained above I may, in some low cases, need to save modified entities that were disconnected. So to audit, I have to retrieve the current values from the database and then compare to work out what was changed while disconnected. If the entity has been tracked, there is no need to get the old values, as I've got access to them via the state manager. I'm not using self tracking entities, as this is overkill for my requirements.
QUESTION: In my auditing method I simply want to know if the modified entity is tracked or not, i.e. do I need to go to the db and get the original values?
Cheers
DbContext.ChangeTracker.Entries (http://msdn.microsoft.com/en-us/library/gg679172(v=vs.103).aspx) returns DbEntityEntry objects for all tracked entities. DbEntityEntry has Entity property that you could use to find out whether the entity is tracked. Something like
var isTracked = ctx.ChangeTracker.Entries().Any(e => Object.ReferenceEquals(e.Entity, myEntity));
We are in a process of designing an application with approx 100 tables and complicated business logic. Windows Forms will be used on the client side and WCF services with MSSQL on the server.
Custom DTOs are used for client-server communication, business entities are not distributed.
Which variant of Entity Framework to use (and why):
EF 4.0 EntityObjects
EF 4.0 POCO
EF 4.1 DbContext
Something else
Database-first approach is a requirement.
Also, is it worth implementing a Repository pattern? It seems a bit redundant, as there is one level of abstraction in the mapping itself and another one in the use of DTOs. I'm currently leaned towards using auto-generated extendable repositories for each entity returning IQueryable, just to have a place to put common queries, but still allowing querying entity model directly from the Service Layer.
Which variant to use? Basically once you have custom DTO the only question is do you want to have control over entities code (their base class) and make them independent on EF? Do you want to use code first? If the answers to all questions are no then you can use EntityObjects. If you want to have entities persistence ignorant or use custom base class you should go to POCO. If you want to use code first or new DbContext API you will need EF 4.1. Some related topics:
EF 4.1 Code-first vs Model/Database-first
EF POCO code only VS EF POCO with Entity Data Model (this was related to CTP)
ADO.NET DbContext Generator vs. ADO.NET POCO Entity Generator
EF Model First or Code First Approach?
There are more things to consider when designing service layer. You should be aware of complications you will have to deal with when using EF in WCF. Your service will provide data to WinForms application and it will work with them in "detached mode". Once user will do all changes he wants to do he will post data back to the service. But here comes the problem - you must tell EF what has changed. If you for example allow user to change order with all its order items (change quantity in items, add new items, delete some items) you must say EF exactly what has changed, what was added and what was deleted. That is easy when you work with single entity but once you allow user to change object graph (especially many-to-many relations) then it is quite tough. The most common solution is loading the whole graph and merge the state from incoming DTOs to loaded and attached graph. Other solution is using Self tracking entities instead of EntityObjects/POCOs + DTOs.
When discussing repositories I would refer you to this answer which refers many other answers discussing repositories, their possible redundancy and possible mistakes when using them just to make your code testable. Generally each layer should be added only if there is real need for the layer - due to better separation of concerns.
The main advantage of POCOs is that those classes can be your DTOs, so if you've already got custom DTOs that you're using, POCO seems a bit redundant. However, there are some other advantages which may or may not have value to you, since you didn't mention unit testing as a requirement. If you plan to write unit tests, then POCO is still the way to go. You probably won't notice much difference between 4.0 POCO and 4.1 since you won't be using the code-first feature (disclaimer: I've only used 4.0 POCO, so I'm not intimately familiar with any minor differences between the two, but they seem to be more or less the same--basically I was already using POCO in 4.0 and haven't seen anything that's made me want to update everything to use 4.1).
Also, depending on whether you plan to unit-test this layer, there's still value in implementing the repository/unit of work patterns when using Entity Framework. It serves to abstract away the data access logic (the context), not the entities themselves, and allows you to do things like mocking your context in unit tests. What I do is copy the T4 template for my context and use it to create the interface, then edit the T4 template for the context and have it implement that interface and use IObjectSet<T> instead of ObjectSet<T>. So instead of:
public class MyEntitiesContext
{
public ObjectSet<MyClass> MyEntities
...
}
I end up with:
public interface IMyEntitiesContext
{
public IObjectSet<MyClass> MyEntities;
}
and
public class MyEntitiesContext : IMyEntitiesContext
{
public IObjectSet<MyClass> MyEntities
...
}
So I guess it really comes down to whether or not you plan to write unit tests for this layer. If you won't be doing anything that would require mocking out your context for testing, then the easiest thing to use would probably be 4.0 EntityObjects, since you aren't planning to pass your entities between layers and it would require the least effort to implement. If you plan to use mocking, then you'll probably want to use POCO and implement repository/unit of work.
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.