miércoles, 28 de enero de 2009

ADO.NET Entity Framework: ¿Cómo cambiar la ForeignKey de un objeto?

Tengo un formulario de edición de un Producto, y entre muchos otros datos, se debe seleccionar, por ejemplo, la Categoría desde un DropDownList. Al guardar el producto, se debe establecer el ID de la categoría asociada.

La intuición nos llevaría a escribir el siguiente código:

product.Category.Id = Convert.ToInt32(CategoryDropDownList.SelectedValue);

Desafortunadamente, esto provocará un error, porque la propiedad Category es null, o bien porque no se puede cambiar la propiedad Id.

Para resolver el problema podemos escribir lo siguiente:

var categoryId = Convert.ToInt32(CategoryDropDownList.SelectedValue);
product.CategoryReference.EntityKey = new EntityKey("ContosoEntities.Categories", "Id", categoryId);

En lugar de la propiedad Category estamos usando la propiedad CategoryReference y estamos asignando una nueva EntityKey. Esto permitirá que cuando ejecutemos el método SaveChanges, los cambios de la categoría asociada al producto se persistan en el almacén de datos.

Particularmente esta forma de resolver el problema me parece poco intuitiva y elegante. Algo tan simple como cambiar una clave externa implica escribir todo ese código. Sin embargo, hasta ahora, parece ser la única forma de resolver el problema.

Si nos interesa mejorar un poco nuestro código, y escribir algo más simple, podríamos crear una clase Partial de Product, y agregar una propiedad CategoryId:

public int CategoryId
{
   get
   {
       return Convert.ToInt32(CategoryReference.EntityKey.EntityKeyValues[0].Value);
   }

   set
   {
       var qualifiedEntitySet = "ContosoEntities.Categories";
       CategoryReference.EntityKey = new EntityKey(qualifiedEntitySet, "Id", value);
   }
}

Esta propiedad adicional, permitirá escribir algo como:

product.CategoryId = Convert.ToInt32(CategoryDropDownList.SelectedValue);

Muy similar a los que habíamos intentado al principio!

Antes de terminar, alguien podrá decir:

"Usando LINQ TO SQL, estas propiedades se generan automáticamente cuando se crea el modelo."

Es cierto! Pueden dirigir sus comentarios y sugerencias al Blog del Equipo de ADO.NET Entity Framework, y quizás tengamos suerte para la siguiente versión.

Hasta la próxima! Espero que sirva.
Saludos, Gus

1 comentario:

Anónimo dijo...

Muchas gracias, llevo una semana intentando hacer esto mismo... pero intentaba asignar directamente un objeto Category que ya tenia cargado previamente en el contexto a la propiedad product.Category y al grabar me daba error. Otra cosa que habia intentado es asignar un objeto Category a la propiedad product.CategoryReference.Value como entendi en un articulo del msdn, pero nada. ¿Podrias explicar que diferencia hay entre lo que tu haces y lo que yo estaba haciendo?

Gracias de antemano