Entity Framework (IV): Mapeo mediante procedimientos almacenados


En el anterior artículo aprendimos cómo mapear un procedimiento almacenado en nuestro Entity Model y hacer uso de él mediante una llamada explícita para eliminar en cascada todos los elementos asociados tanto a los clientes como a los pedidos.

Entity Framework proporciona la opción de personalizar los métodos de inserción, eliminación y actualización a través de procedimientos almacenados, haciendo que éstos se realicen mediante la sintaxis natural de Entity Framework pero permitiéndonos a nosotros indicar, a través de procedimientos almacenados, la forma de hacerlo.

Es importante saber que Entity Framework tiene una política de todo o nada para hacer uso de esta característica, es decir: si se decide utilizar un procedimiento almacenado para realizar las eliminaciones, será obligatorio definir también los métodos de inserción y actualización.

Ya definimos antes un procedimiento para las eliminaciones, llamado sp_Cliente_DeleteCascade. Codificaremos ahora un procedimiento almacenado para realizar las inserciones y otro para las actualizaciones.

El procedimiento de inserción recibirá como parámetros los componentes del registro salvo el identificador, que será generado automáticamente. Además, devolverá como valor de retorno la llamada al método SCOPE_IDENTITY(), que almacenará el valor del IdCliente generado para el registro insertado. A este valor le daremos un nombre para poder identificarlo en nuestro mapeo, por ejemplo, “id”.


       create procedure sp_Cliente_Insert
              @Nombre nvarchar(256),
              @FechaNacimiento date
       as
       begin
              set nocount on;

              -- Realizamos la inserción
              insert  into Cliente(Nombre, FechaNacimiento)
                     values(@Nombre, @FechaNacimiento);

              -- Devolvemos el nuevo id insertado
              select SCOPE_IDENTITY() as id;
       end;

El procedimiento de actualización será similar: contará con todos los valores del registro y realizará la comparación por el ID, tal y como se muestra a continuación:


       create procedure sp_Cliente_Update
              @IdCliente int,
              @Nombre nvarchar(256),
              @FechaNacimiento date
       as
       begin
              set nocount on;

              -- Realizamos la actualización
              update  Cliente set Nombre = @Nombre, FechaNacimiento = @FechaNacimiento
                      where IdCliente = @IdCliente;

       end;

Una vez compilados nuestros procedimientos, nos dirigiremos al explorador de modelo y haremos click derechos sobre la parte correspondiente a la base de datos, seleccionando la opción Update Model from Database…

Hecho esto, seleccionaremos los procedimientos que acabamos de crear y esperaremos a que termine la actualización de nuestro modelo, tras lo cual seleccionaremos la entidad que queremos modificar (en este caso, Cliente) y haremos click derecho seleccionando Stored Procedure Mapping para proceder con el mapeo de los procedimientos almacenados.

Se mostrarán ahora tres opciones: inserción, actualización y eliminación. Desplegaremos cada uno de los elementos y seleccionaremos el procedimiento adecuado para cada función.

Tras rellenar los tres elementos, se nos debería mostrar algo como lo siguiente, realizando el mapeo entre los parámetros del procedimiento y las propiedades de nuestros objetos:

Sólo nos queda un detalle: en la inserción queremos que el campo IdCliente se rellene automáticamente en nuestro objeto tras la inserción. ¿Cómo lograr eso? Si recordamos, el procedimiento ejecutaba la siguiente sentencia al finalizar la inserción:


         -- Devolvemos el nuevo id insertado
         select SCOPE_IDENTITY() as id;

Por lo tanto, devolveremos en un parámetro denominado ‘id’ el valor del identificador del nuevo cliente. Sabiendo esto, añadiremos ‘id’ debajo de Result Column Bindings bajo el procedimiento de inserción, y le asignamos la propiedad IdCliente como objetivo. De este modo, el campo IdCliente adquirirá este valor una vez finalizada la inserción.

Para finalizar, ejecutaremos una actualización o una inserción de la forma habitual. A partir de ahora, serán nuestros procedimientos almacenados los que se encarguen, en silencio, de realizar estas tareas por nosotros.


            // Instanciamos el DbContext
            var dbContext = new testdbEntities();

            // Realizamos la consulta
            var clientes = dbContext.Clientes.Where(cliente => cliente.Nombre.StartsWith("Kat"));

            // Modificamos los objetos que consideremos oportunos
            foreach (var cliente in clientes)
                cliente.Nombre = cliente.Nombre.Replace("Katia", "Katerina");

            // Guardamos los cambios
            dbContext.SaveChanges();

            // Comprobamos si todo es correcto
            foreach (Cliente cliente in dbContext.Clientes)
            {
                Console.WriteLine(string.Format("ID: {0}\tNOMBRE: {1}\tAÑO NAC: {2}",
                    cliente.IdCliente, cliente.Nombre, cliente.FechaNacimiento.Year));
            }

One comment

  1. Muy buen aporte, una consulta como obtengo el valor del Id (SCOPE_IDENTITY())?…Por ejemplo yo hago lo siguiente:
    using (miBD context = new miBD())
    {
    //Ejecuto mi inserción llamando a mi SP.
    context.miProcedureInsert(dato1,dato2,dato3);

    //ahora como obtengo mi ID?
    /*
    int codigoGenerado = ????
    */
    }

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s