Saving Changes to Related Objects in a Detached State with Entity Framework

c# entity-framework northwind

Question

I'm using the Northwind database as an example for this post where I am having a problem saving detached entities back to the database using the entity framework.

I have the following two methods to get me the territories and the regions:

    static List<Region> GetRegions()
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Region.MergeOption = System.Data.Objects.MergeOption.NoTracking;
            return entities.Region.ToList();
        }
    }

    static List<Territories> GetTerritories()
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Territories.MergeOption = System.Data.Objects.MergeOption.NoTracking;
            return entities.Territories.ToList();
        }
    }

These methods both work fine and get me the collection of objects I require in the detached state.

I also have a static method called SaveEntity, which takes in both an old entity and the currently editted entity, this is as follows:

    static void SaveEntity(EntityObject oldEntity, EntityObject newEntity)
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Attach(oldEntity);
            entities.ApplyPropertyChanges(newEntity.EntityKey.EntitySetName, newEntity);
            entities.SaveChanges();
        }
    }

This method partially works where the changes to the object are saved down to the database, but any changes to the relationship of related objects are not saved.

I have the following code calling the above methods as my example:

            List<Territories> territories = GetTerritories();
        List<Region> regions = GetRegions();

        Region region = regions.Where(n => n.RegionID == 2).FirstOrDefault();
        Territories oldTerritory = territories.Where(n => n.TerritoryID == "01581").FirstOrDefault();
        Territories newTerritory = ObjectCopier.Clone<Territories>(oldTerritory);

        newTerritory.TerritoryDescription = "Hello World";
        newTerritory.Region = region;

        SaveEntity(oldTerritory, newTerritory);

The change to TerritoryDescription is successfully saved, but the change to Region is not, in the database it still remains as RegionID=1 instead of RegionID=2.

Can anyone provide me with some insight to why ApplyPropertyChanges doesn't propogate changes to related objects?

Also, does anyone know of how I can get around this problem?

1
7
4/6/2010 10:03:45 PM

Popular Answer

Instead of fetching regions and territories seperately, fetch both of them in the same query. Something like (I assume you want to update the entity, do not want to create a new one);

static List<Region> GetTerritoriesWithRegions()
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Territories.MergeOption = System.Data.Objects.MergeOption.NoTracking;
            return entities.Territories.Include("Region").ToList();
        }
    }

Then update them as the following;

   List<Territories> territoriesWithRegions = GetTerritoriesWithRegions();
        Territories territory = territories.Where(n => n.TerritoryID == "01581").FirstOrDefault();
        territory.TerritoryDescription = "Hello World";
        Region region = territories.Where(p => p.Any(q => q.Region.RegionID == 2)).FirstOrDefault().Region;
        territory.Region = region;

        SaveEntity(territory);

And save them;

static void SaveEntity(EntityObject entity)
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Attach(entity);
            entities.Context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);            
            entities.SaveChanges();
        }
    }

I have coded this on notepad so there may be mistakes; if any please comment so I will update accordingly.

2
4/20/2012 8:59:56 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow