Refresh an object in Entity Framework 4. Do I need to download everything first?

I may be wrong, but a simple insert and update using EF4 is driving me crazy. (New to EF)

I created a noddy project and downloaded here

http://cid-9db5ae91a2948485.office.live.com/browse.aspx/PublicFolder?uc=1http://cid-9db5ae91a2948485.office.live.com/browse.aspx/PublicFolder?uc=1

Feel free to download if you want and fix the problem. That would be fantastic.

In short, I would like someone to tell me that what I suspect is wrong.

Suppose you have a client object. You need to download it first before updating, how do you do to uninstall? It seems crazy to me.

Given that you have a save method (both insert and update are done here), and you pass it to the client. You already have all the details. How do you change to make it work? I get all kinds of errors. Do I need to go to db every time I need to change my client’s child?

public void Save(CustomerDTO customerDTO) { //convert dto to EF entity var entityCustomer=ToEntityCustomer(customerDTO) using(ctx=new CustomerContext()) { if(efCustomer.CustomerId > 0) { //UPDATE //DO I NEED TO FETCH MY CUSTOMER AGAIN FROM THE DB EVEN THOUGH I ALREADY HAVE //HAVE ALL THE DETAILS? I have not done it here.????? ctx.Customers.Attach(entityCustomer); ctx.ApplyCurrentValues(entityCustomer); //Also Customer has addresses so foreach(var address in entityCustomer.Addresses) { //some may be new addresses some might be modified one ?????? lost } } else { ///INSERT ctx.Customers.AddObject(entityCustomer); ctx.ObjectStateManager.ChangeObjectState(entityCustomer,EntityState.Added); foreach(var address in entityCustomer.Addresses) { ctx.ObjectStateManager.ChangeObjectState(address ,EntityState.Added); } } ctx.SaveChanges(); } } 
+4
source share
2 answers

This is one way to do this if you do not want to retrieve objects before saving:

 public bool Save(CustomerInfo customerInfo) { var entityCustomer = ToEntityCustomer(customerInfo); using (var ctx = new CustomerContext()) { ctx.ContextOptions.LazyLoadingEnabled = false; DataAccess.Address[] addresses = new DataAccess.Address[entityCustomer.Addresses.Count]; entityCustomer.Addresses.CopyTo(addresses, 0); entityCustomer.Addresses.Clear(); if (customerInfo.Id == 0) { ctx.Customers.AddObject(entityCustomer); } else if (customerInfo.Id > 0) { ctx.Customers.Attach(entityCustomer); ctx.ObjectStateManager.ChangeObjectState(entityCustomer, EntityState.Modified); } foreach (var address in addresses) { if (address.AddressID == 0) { ctx.Addresses.AddObject(address); entityCustomer.Addresses.Add(address); } else if (address.AddressID > 0) { ctx.Addresses.Attach(address); ctx.ObjectStateManager.ChangeObjectState(address, EntityState.Modified); if (customerInfo.Id == 0) { // New Customer so we need to add the existing addresses // since the FK on Address is 0 entityCustomer.Addresses.Add(address); } } } ctx.SaveChanges(); return true; } } 

The trick is to remove the child elements (e.g. Addresses) immediately before doing the Attach / AddObject on the parent (e.g. Customer), as these 2 operations will affect the entire schedule and this will cause all kinds of problems.

+4
source

You do not need to download the object before updating - check this answer . But if you want to work with related objects, this is really useful. In your case, the Address object is probably related to Customer enity in a one-to-many relationship. If you want to change the client with addresses without loading the graph of objects, you need to know which addresses have been changed, inserted and deleted. For a one-to-many relationship, this can usually be modeled with the following rules:

  • Id = 0 means a new object
  • Id> 0 means update (so you update even if the address has not changed)
  • Id <0 means delete (current identifier is the negation of the deleted identifier)

You can see that this method is not very good, because you always update unchanged objects, and you have to handle deletions differently, and then just delete them from the Addresses collection in the Customer object. Also, this method only works for aggregates where a linked community cannot exist without a parent entity. If you can only delete the relationship, but the object remains in the database, this method is useless, and you need to find another mechanism for tracking changes - this is exactly what happens if you want to track changes in many ways. This is why I abandoned this technique and why I load the changed data from the database before processing the changes. There is also another message about this issue.

If you don’t want to monitor the status yourself, you can check the self-examination objects (STEs), but keep in mind their shortcomings .

Btw. a delete operation can also be performed without first loading the object. Usually you can create a dummy object (empty) and set only its Id and concurrency handler (I always use timestamp). Then you can attach this object to the context and delete it. But this will not work if the subject is in a childlike relationship to another resolution. In this case, you also have to manually delete the relation, otherwise an exception will be thrown. This will not happen if you first load the object from the database.

+3
source

All Articles