Entity Framework Service Layer Update POCO

2019-04-12 13:23发布

问题:

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?

回答1:

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.



回答2:

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 :)



回答3:

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.