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?

share|improve this question
As an aside, you can write context.Categories.First(c => c.Id == car.Category.Id). – Marcelo Cantos Apr 11 '10 at 0:12
feedback

1 Answer

up vote 1 down vote accepted

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");
}
share|improve this answer
feedback

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.