views:

118

answers:

1

This is a method for add/update an entity using Self Tracking Entities, what is the equivalent using POCO?

        public Hero SaveHero(Hero hero)
        {
            using (WarEntities model = new WarEntities())
            {
                if (hero.ChangeTracker.State == ObjectState.Added)
                {
                    model.Heroes.AddObject(hero);
                    model.SaveChanges();
                    hero.AcceptChanges();
                    return hero;
                }
                else if (hero.ChangeTracker.State == ObjectState.Modified)
                {
                    model.Heroes.ApplyChanges(hero);
                    model.SaveChanges();
                    return hero;
                }
                else
                    return null;
            }
        }
+1  A: 

The most straightforward way to update an entity is to fetch it by Id, rewrite all the properties and call SaveChanges():

public Hero SaveHero(Hero hero)
{
    using (WarEntities model = new WarEntities())
    {
        Hero dbHero = model.Heroes.FirstOrDefault(h => h.Id == hero.Id);
        if (dbHero != null)
        {
            dbHero.Name = hero.Name;
            dbHero.OtherProperties = hero.OtherProperties;
            ...
            model.SaveChanges();
            return dbHero;
        }
        else
        {
            model.Heroes.AddObject(hero);
            model.SaveChanges();
            return hero;
        }
    }

However, you can avoid fetching the entity from the DB by attaching the POCO entity and changing it's state to Modified:

public Hero SaveHero(Hero hero)
{
    using (WarEntities model = new WarEntities())
    {
        model.Heroes.Attach(hero);
        var heroEntry = model.ObjectStateManager.GetObjectStateEntry(hero);
        heroEntry.ChangeState(EntityState.Modified);
        model.SaveChanges();
        return hero;
    }

Note that this method will only work if you already have this "hero" in the DB and are updating the existing entry. You will need a separate method for adding a new "hero".

Yakimych
How does the ObjectContext know which properties of the entity actually have been changed when you're using the second option (changing the ObjectState for the entity)? I guess that the generated SQL command is an UPDATE statement which includes simply ALL database columns. Is that correct? If so, updating might be less efficient than changing property by property (your first option) where change tracking notices which properties have really changed and a more efficient UPDATE statement is generated. I'm not sure if I interprete benefit and drawback of the two options correctly.
Slauma
Yes, you are correct, the second option will update all the properties. I don't think the performance gain would be noticeable with the first version, though (unless you do huge batch updates with lots of data).
Yakimych