views:

182

answers:

1

Hi people. I'm trying to update an entity and its related entities as well. For instance, I have a class Car with a property Category and I want to change its Category. So, I have the following methods in the Controller:

public ActionResult Edit(int id)
    {
        var categories = context.Categories.ToList();
        ViewData["categories"] = new SelectList(categories, "Id", "Name");
        var car = context.Cars.Where(c => c.Id == id).First();
        return PartialView("Form", car);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Car car)
    {
        var category = context.Categories.Where(c => c.Id == car.Category.Id).First();
        car.Category = category;
        context.UpdateCar(car);
        context.SaveChanges();
        return RedirectToAction("Index");
    }

The UpdateCar method, in ObjectContext class, follows:

public void UpdateCar(Car car)
    {
        var attachedCar = Cars.Where(c => c.Id == car.Id).First();
        ApplyItemUpdates(attachedCar, car);
    }

    private void ApplyItemUpdates(EntityObject originalItem, EntityObject updatedItem)
    {
        try
        {                
            ApplyPropertyChanges(originalItem.EntityKey.EntitySetName, updatedItem);
            ApplyReferencePropertyChanges(updatedItem, originalItem);
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }        

    public void ApplyReferencePropertyChanges(IEntityWithRelationships newEntity, IEntityWithRelationships oldEntity)
    {
        foreach (var relatedEnd in oldEntity.RelationshipManager.GetAllRelatedEnds())
        {
            var oldRef = relatedEnd as EntityReference;
            if (oldRef != null)
            {
                var newRef = newEntity.RelationshipManager.GetRelatedEnd(oldRef.RelationshipName, oldRef.TargetRoleName) as EntityReference;
                oldRef.EntityKey = newRef.EntityKey;
            }
        }
    }

The problem is that when I set the Category property after the POST in my controller, the entity state changes to Added instead of remaining as Detached.

How can I update one-to-one relationship with Entity Framework and ASP.NET MVC without setting all the properties, one by one like this post?

+1  A: 

Ok people, I just found out how it can be solved. Instead of setting the whole object in the Category property, it is necessary to set only the entity key in the reference property.

So, this is wrong:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Car car)
{
    var category = context.Categories.Where(c => c.Id == car.Category.Id).First();
    car.Category = category;
    context.UpdateCar(car);
    context.SaveChanges();
    return RedirectToAction("Index");
}

And this is the right way:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Car car)
{
    var category = context.Categories.Where(c => c.Id == car.Category.Id).First();
    car.CategoryReference.EntityKey = category.EntityKey;
    context.UpdateCar(car);
    context.SaveChanges();
    return RedirectToAction("Index");
}
Kitaly