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

c# entity-framework northwind

Question

For the sake of this article, I'll use the Northwind database as an example, where I'm having trouble utilizing the entity framework to save detached entities back to the database.

I have two options for getting the regions and the territories:

    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();
        }
    }

Both of these approaches are effective in giving me the collection of items I need in the detached state.

Additionally, I have a static function called SaveEntity that accepts both an old entity and the entity that is presently being edited, and it works 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();
        }
    }

The modifications to the item are saved to the database using this technique, but any changes to the relationships between related objects are not recorded.

As my example, I'll use the code below, which calls the aforementioned methods:

            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 modification to TerritoryDescription is properly recorded, but the modification to Region is not; in the database, RegionID=1 rather than RegionID=2 still appears.

Could someone please explain why ApplyPropertyChanges doesn't propagate changes to connected objects?

Does anybody also have any suggestions on how I might avoid this issue?

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

Popular Answer

Use one query to get both regions and territories rather than doing it separately. Assuming you want to update the object rather than create a new one, something like;

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

then make the following changes to them:

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

saving them;

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

Please remark if you see any errors since I have coded this on notepad and will update as necessary.

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