jueves, 13 de enero de 2011

asp.net MVC 3.0 EF4 DELETE y UPDATE

Vaya título me ha salido!!

Haciendo mi primera aplicación CRUD en MVC 3.0 + Entity Framework 4.0 me encuentro que hay montones de ejemplos de listado e inserción de registros pero la cosa se empieza liar un poquillo con borrado y bastante más con actualización.

Como el problema no están en el controlador ni en la vista, si no en el modelo y en los métodos que hay que construir para hacer ambas acciones (y de lo que no hay información en castellano, o no la he encontrado en Google), aquí las pongo. Que son ligeramente diferentes que en linq to sql.

        internal static void Delete(Clubs club)
{
ArqueriaModelContainer arqueriaContext = new ArqueriaModelContainer();
arqueriaContext.AttachTo("Clubs", club);
arqueriaContext.DeleteObject(club);
}

internal static void ActualizaClub(Clubs Club)
{
ArqueriaModelContainer arqueriaContext = new ArqueriaModelContainer();
arqueriaContext.AttachTo("Clubs", Club);
arqueriaContext.ObjectStateManager.ChangeObjectState(Club, EntityState.Modified);
arqueriaContext.SaveChanges();
}


Como habrás notado, mi aplicación se centra en la gestión de arqueros y estos dos métodos borran y modifican un club. Por lo cual tengo objetos del tipo Clubs –que es una entidad que mapea la tabla Clubs – y el contexto llamado ArqueriaModelContainer.



Cosas interesantes. Que como lo que me traigo es una entidad sin enlazar con el contexto, lo primero que hay que hacer es enlazarla con el método attach. A continuación puedes borrarla directamente, o cambiarle el estado de la entidad a modificado para poder salvar los cambios.



Cosa que no hay que hacer, declarar una propiedad de la clase que instancie el contexto, porque da problemas al intentar enlazar una entidad que ya está enlazada, en el caso de la actualización. Supongo que con tiempo para darle vueltas y refactorizando, se puede hacer mucho mejor.



Pero cómo obtengo la entidad Club de la vista. Pues un poco de magia de MVC que no tengo claro aún cómo lo hace pero en el controlador tengo este código:



public ActionResult Edit(int id)
{
Clubs club = ClubsModel.GetClubById(id);
if (club == null)
{ return View("NotFound"); }
else
{ return View(club); }
}
[HttpPost]
public ActionResult Edit(Clubs club)
{
ClubsModel.ActualizaClub(club);
return RedirectToAction("Index");
}


En la primera parte recupera de la queryString el id del Club que quiero modificar y le envío la entidad entera por la vista. En la segunda parte, recupero la entidad que he enviado en la primera. Si, entera y sin tener que hacer tediosas cargas del contenido de los controles en los campos de la entidad. El código en la página Razor se obtiene de forma tan simple como, pulsando con el botón derecho en el segundo ActionResult, decirle que quieres una vista fuertemente tipada con la plantilla de edit.



@model Arqueria.Models.Clubs
@{
Layout = null;
}
<!DOCTYPE html>
<
html>
<
head>
<
title>Edit</title>
</
head>
<
body>
@using (Html.BeginForm()) {
<fieldset>
<
legend>Clubs</legend>
@Html.HiddenFor(model => model.idClub)
<div class="editor-label">
@Html.LabelFor(model => model.nombre)
</div>
<
div class="editor-field">
@Html.EditorFor(model => model.nombre)
@Html.ValidationMessageFor(model => model.nombre)
</div>
<
div class="editor-label">
@Html.LabelFor(model => model.identificador)
</div>
<
div class="editor-field">
@Html.EditorFor(model => model.identificador)
@Html.ValidationMessageFor(model => model.identificador)
</div>
<
div class="editor-label">
@Html.LabelFor(model => model.domicilio)
</div>
<
div class="editor-field">
@Html.EditorFor(model => model.domicilio)
@Html.ValidationMessageFor(model => model.domicilio)
</div>
<
div class="editor-label">
@Html.LabelFor(model => model.cp)
</div>
<
div class="editor-field">
@Html.EditorFor(model => model.cp)
@Html.ValidationMessageFor(model => model.cp)
</div>
<
div class="editor-label">
@Html.LabelFor(model => model.localidad)
</div>
<
div class="editor-field">
@Html.EditorFor(model => model.localidad)
@Html.ValidationMessageFor(model => model.localidad)
</div>
<
div class="editor-label">
@Html.LabelFor(model => model.provincia)
</div>
<
div class="editor-field">
@Html.EditorFor(model => model.provincia)
@Html.ValidationMessageFor(model => model.provincia)
</div>
<
p>
<
input type="submit" value="Save" />
</
p>
</
fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
</
body>
</
html>


Por razones de longitud del post, no pongo la página index, que es el mero listado de los clubs.

Espero que le sea de utilidad a alguien más que a mi.

No hay comentarios: