SlideShare una empresa de Scribd logo
LINQ to SLQ (Parte 7 – Actualizando la base de datos con procedimientos almacenados) 
9 respuestas 
En las últimas semanas he escrito una serie de post sobre LINQ to SQL. Es un ORM integrado en .NET 3.5, y nos permite modelar bases de datos relacionales con clases de .NET. Podemos usar expresiones LINQ para consultar a la base de datos, actualiazarla, insertar y borrar datos. 
Aquí tenéis los enlaces a los otros post: 
 Parte 1: Introducción a LINQ to SQL 
 Parte 2: Definiendo el modelo de datos. 
 Parte 3: Consultando la base de datos 
 Parte 4: Actualizando la base de datos. 
 Parte 5: Enlazar controles de interfaz de usuario con el ASP:LinqDatSource 
 Parte 6: Obtener datos con procedimientos almacenados. 
En la sexta parte vimos cómo podemos usar procedimientos almacenados (SPROCs) y funciones definidas por el usuario (UDFs) para consultar la base de datos con el modelo de datos de LINQ to SQL. En el post de hoy veremos cómo podemos usar los SPROCs para actualizar/insertar/borrar datos de nuestra base de datos. 
Para ayudar a entender esto empezaremos costruyendo una capa de datos para la base de datos de ejemplo Northwind: 
Paso 1: Crear nuestra capa de acceso a datos (sin SPROCs) 
En la segunda parte de esta serie vimos cómo usar el diseñador de LINQ to SQL de VS 2008 para crear el siguiente modelo de clases:
Añadiendo reglas de validación a nuestro modelo de clases. 
Después de definir nuestro modelo querremos añadir reglas de validación a nuestro modelo de datos. Podemos hacer esto añadiendo clases parciales a nuestro proyecto y añadir las reglas de validación en esas clases (vimos cómo hacer esto en la cuarta parte de esta serie). 
Por ejemplo, podemos añadir la lógica necesaria para asegurarnos de que el número de teléfono de los clientes siguen un patrón válido, y otra para asegurarnos de que la fecha de entrega (RequierdDate) es posterior a la fecha actual del pedido (OrderDate). Una vez que hemos definido las clases parciales, estos métodos de validación se ejecutarán cada vez que escribamos código para actualizar nuestros objetos de datos de nuestra aplicación: 
VB:
C#:
Añadir un método de ayuda GetCustomer() a nuestro DataContext 
Una vez que hemos creado nuestro modelo de clases, y que le hemos añadido reglas de validación, podemos consultar e interactuar con los datos. Podemos hacer esto escribiendo expresiones LINQ sobre nuestro modelo de clases (vimos cómo hacer esto en la tercera parte de esta serie). También podemos mapear SPROCs en nuestro DataContext (esto lo vimos en la sexta parte de la serie). 
Cuando creamos una capa de datos con LINQ to SQL normalmente querremos encapsular consultas comunes de LINQ (o SPROCs) en métodos auxiliares que añadiremos a la clase DataContext. Esto lo conseguimos añadiendo una clase parcial a nuestro proyecto. Por ejemplo, podemos añadir un método llamado "GetCustomer()" que nos permita buscar y obtener objetos Customer de la base de datos a partir del valor CustomerID: 
VB:
C#: 
Paso 2: Usando nuestra capa de datos (seguimos sin SPROCs) 
Ya tenemos una capa de datos que encapsula nuestro modelo de datos, integra reglas de validación, y nos permite consultar, actualizar, insertar y borrar datos. 
Veamos ahora un escenario simple usándolo para obtener un objeto customer existente, actualizamos el ContactName y el PhoneNumber, y creamos un nuevo objeto Order para asociarlos. El siguiente código hace todo eso en una sola transacción. LINQ to SQL se asegura de que las reglas de validación se cumplen ántes de guardar nada en la base de datos: 
VB:
C#: 
LINQ to SQL monitoriza todas las modificaciones de los objetos que hemos obtenido de la base de datos, y guarda los objetos que añadimos. Cuando llamamos al método DataContext.SubmitChanges(), LINQ to SQL comprueba las reglas que hemos establecido, y genera automáticamente la SQL que actualizará el registro de Customer e insertará un nuevo registro en la tabla Orders 
Un momento - Pensaba que este post iba sobre SPROCs 
Si aún estais leyendo, os preguntaréis dónde están los SPROCs en este post. ¿Porque os estoy mostrando el código de arriba que hace que se genere una SQL dinámica? ¿Por qué no os he enseñado cómo llamar a un SPROC para hacer las inserciones/actualizaciones/borrados todavía? 
La razón es que el modelo de programación de LINQ to SQL tanto para trabajar con objetos modelados mediante SPROC es exactamente el mismo que con SQL dinámico. La manera en que añadimos validación lógica es exactamente igual (así que todas las reglas que hemos añadido a nuestro modelo de datos se aplicarán también si usamos SPROCs). El código anterior que hemos usado para obtener un cliente, actualizarlo y añadir un nuevo pedido es exactamente igual tanto si usamos SQL dinámico como si usamos SPROCs.
Esta simetría en el modelo de programación es muy potente ya que no tenemos que aprender dos maneras diferentes de hacer las cosas, ni tenemos que decidir al principio del proyecto qué técnica usar, si SPROC o no. Podemos empezar usando el SQL dinámico que nos da LINQ to SQL para las consultas, inserciones, actualizaciones y borrados. Podemos añadir reglas de validación a nuestro modelo. Y luego podemos actualizar el modelo de datos para usar SPROCs - o no. El código y los test que escribamos contra las clases del modelo de datos serán exáctamente iguales. 
De ahora en adelante veremos cómo podemos actualizar nuestro modelo de datos usando SPROCs para actualizar/insertar/borrar - mientras seguimos usando las mismas reglas de validación y trabajaremos con los mismos códigos anteriores. 
Cómo usar SPROCs en inserciones, actualizaciones y borrados 
Podemos modificar la capa de datos que estamos construyendo para que use SPROCs, en lugar de SQL dinámico de dos maneras: 
1. Usando el diseñador de LINQ to SQL para configurar gráficamente la ejecución de los SPROCs en las diferentes operaciones o 
2. Añadir una clase parcial NorthwindDataContext a nuestro proyecto, y entonces implementar los métodos necesarios para la inserción, borrado y actualización. (por ejemplo: InsertOrder, UpdateOrder, DeleteOrder) que serán llamados cuando se realize alguna de las operaciones asociadas. Estos métodos parciales serán pasados a las instancias del modelo de datos que queramos actualizar, y podemos ejecutar tanto SPROC como código SQL para guardarlo. 
Cuando usemos la primera aproximación para configurar gráficamente los SPROCs que llamaremos, por debajo se está generando el mismo código (en clases parciales que crea él solo) que escribiríamos si elegimos la segunda opción. En general os recomiendo que uséis el diseñador de LINQ to SQL para configurar los SPROCs en el 90% de los casos - y crear las llamadas personalizadas a procedimientos almacenados en escenarios más avanzados. 
Paso 3: Hacer otras inserciones con un SPROC 
Empezaremos cambiando nuestro modelo de datos para que use SPROCs con el objeto Order. 
Primero nos vamos a la ventana de "Explorador de Servidores" (Server Explorer) de Visual Studio, expandimos el nodo "Stored Procedures" de nuestra base de datos, hacemos clic con el botón derecho y elegimos la opción "Add New Stored Procedure": 
Creamos el nuevo procedimiento almacenado que llamaremos "InsertOrder" que añade una nueva fila order a la tabla Orders:
Fijáos que hemos definido el parámetro "OrderId" como un parámetro de salida. ESto es debido a que la columna OrderID es una columna identidad que se autoincrementa cada vez que se añade un nuevo registro. Quien llame a este SPROC deverá pasarle un valor null en ese parámetro - y el SPROC devolverá en ese parámetro el nuevo valor OrderID (llamando a la función SCOPE_IDENTITY() al final del SPROC). 
Después de crear el SPROC abrimos el diseñador de LINQ to SQL. De la misma forma que vimos en la sexta parte de esta serie, podemos arrastrar y soltar SPROCs desde la ventana "server explorer" al diseñador. Esto es lo que haremos con el nuevo SPROC que acabamos de crear:
El último paso será decirle a nuestra capa de datos que use el SPROC InsertOrder cuano inserter un nuevo objeto Order en la base de datos. Esto lo hacemos seleccionando la clase "Order" del diseñador LINQ to SQL, y en las propiedades clicamos el botón "..." del método Insert: 
Hacemos clic en el botón "..." y aparecerá una ventana que nos permite personalizar las operaciones de inserción:
Fijaos cómo el modo po defecto ("Use Runtime") está configurado para usar LINQ to SQL como generador dinámico de las SQL. Para cambiarlo seleccionamos el radio buton "Customize" y seleccionamos el SPROC InsertOrder de la lista de SPROCS disponibles: 
El diseñador de LINQ to SQL calculará una lista de parametros para el SPROC que hemos seleccionado, permitiéndonos mapear las propiedades de nuestra clase Order a los parámetros del SPROC InsertOrder. Por defecto seleccionará el que más se parezca en el nombre. Podemos cambiarlo si queremos.
Una vez que cliquemos en OK está listo. Ahora cada vez que añadamos un nuevo pedido a nuestro DataContext e invoquemos al método SubmitChanges(), se ejecutará el SPROC InsertOrder. 
Importante: Aunque estemos usando SPROC para la persistencia, el método parcial "OnValidate()" que creamos (en la primer parte de esta serie) para encapsular las reglas de validación para los pedidos seguirán ejecutándose antes de realizar cualquier cambio. Es decir, tenemos una forma limpia de encapsular la lógica de negocio y las reglas de validación en nuestros modelos de datos, y podemos reutilizarlos tanto si usamos SQL o SPROCS. 
Paso 4: Actualizando los clientes con SPROCs. 
Ahora vamos a modificar el objeto Customer para manejar las actualizaciones con un SPROC. 
Empezamos creando el SPROC "UpdateCustomer": 
Fijaos que además de pasar el parámetro @CustomerID, también tenemos un parámetro @Original_CustomerID. La columna CustomerID de la tabla Customers no es un campo autoincremental, y puede modificarse cuando hagamos una actualización. Por tanto necesitamos ser capaces de decirle al SPROC cual es el CustomerID original y el nuevo CustomerID. Vamos a ver cómo mapeamos esto con el diseñador de LINQ to SQL. 
Veréis que estamos pasando un parámetro llamado @Version (que es una marca de tiempo) al SPROC. Es una nueva columna que he añadido a la tabla Customers para ayudarme a controlar la concurrencia optimista. Veremos en más detalle este tema en otro post de esta serie - pero en resumen es que LINQ to SQL soporta completamente la concurrencia optimista, y nos permite usar tanto una marca de tiempo o usar valores original/nuevo para detectar si ha habido algún cambio por parte de otro usuario ántes de guardar los datos. Para este ejemplo usaremos una marca de tiempo ya que hace que el código sea mucho más claro. 
Una vez que tenemos nuestro SPROC, lo arrastramos y soltamos al diseñador LINQ to SQL para añadirlo como método a nuestro DataContext. Seleccionamos la clase Customer y hacemos clic en el botón "..." de la propiedad Update:
Seleccionamos el radio button "Customize" y seleccionamos el SPROC UpdateCustomer: 
Cuando mapeamos las propiedades de los objetos Customer con los parámetros del SPROC, veremos que tenemos que decidir si poner la propiedad "current" en el objeto de datos, o si poner el valor original que estaba en la base de datos antes de obtener el objeto. Por ejemplo, tendremos que asegurarnos de que mapeamos el valor "current" de la propiedad CustomerID en el parámetro @CustomerID, y el valor original en el parámetro @original_customerID.
Cuando hacemos clic en OK ya esta terminado. Ahora cuando actualizemos cualquier cliente y llamemos a SubmitChanges() se ejectuará el SPROC UpdateCustomer en lugar de ejecutarse un SQL dinámico. 
Importante: Aunque ahora estemos usando SPROC, el método parcial "OnPhoneChanging()" de la clase Customer (que creamos en el primer post de esta serie) para validar los números de teléfono se seguirá ejecutando de la misma manera ántes de que se guarden los cambios. Tenemos de esta forma una forma limpia de encapsular reglas de negocio y validación a nuestros modelos de datos, y podemos reutilizarlos tanto si usamos SQL dinámico o SPROCs. 
Paso 5: Usando el modelo de datos otra vez (esta vez con SPROCs) 
Ahora que ya tenemos configurada nuestra capa de datos para usar SPOCs en lugar de SQL dinámico, podemos ejecutar el mismo código que vimos en el paso 2: 
Ahora las actualizacion del objeto Customer, y la inserción del objeto ORder, se están ejecutando a través de SPROCs en lugar de SQL dinámico. La lógica de validación que definimos se siguen ejecutando como antes, y el código sigue siendo exactamente el mismo. 
Apuntes avanzados cuando usamos SPROCs 
Veamos unas cuantas recomendaciones útiles para escenarios con SPROC más avanzados con LINQ to SQL 
Uso de parámetros de salida 
En casos de inserción (Paso 3) hemos visto cómo podemos devolver el nuevo valor OrderID (que es un valor identidad y autoincremental de la tabla Orders) usando un parámetro de salida en el SPROC. No estamos limitados a devolver sólo valores de columnas identidad con SPROCs y LINQ to SQL - en realidad podemos actualizar y devolver cualquier parámetro. Podemos usarlo tanto para insetar como para actualizar. LINQ to SQL tomará el valor resultado y actualizará la propiedad asociada en el modelo de dato sin que tengamos que hacer ninguna consulta extra para refrescarlo o calcularlo de nuevo. 
¿Que pasa si el SPROC da un error? 
Si el SPROC da un error mientras inserta, actualiza o borra un dato, LINQ to SQL cancelará y deshará la transacción de todos los cambios asociados a la llamada SubmitChanges(). De manera que nos aseguramos la consistencia de los datos. 
¿Podemos escribir código en lugar de usar el diseñador para llamar a un SPROC? 
Como ya comenté al principio, podemos usar tanto el diseñador de LINQ to SQL para mapear las operaciones con SPROC o podemos añadir métodos parciales a la clase DataContext programáticamente e invocarlos nosotros mismo.
Aquí tenéis un ejemplo del código que deberíamos escribir para sobreescribir el método UpdateCustomer de la clase NorthwindDataContext: 
Este código es el que fué generado con el diseñador de LINQ to SQL cuando lo usamos para mapear el SPROC y asociarlo a la operación de Update del objeto Customer. Podemos usarlo como un punto de partida y añadir alguna lógica adicional para hacerlo más personalizado (por ejemplo: usar el valor de retorno del SPROC para lanzar excepciones personalizadas). 
Resumen 
LINQ to SQL es un ORM muy flexible. Nos permite escribir código limpio orientado a objetos para obtener, acutalizar e insertar datos. 
Lo mejor de todo es que nos permite diseñar una capa de datos realmente limpia e independiente de cómo se guardan y cargan los datos de la base de datos. Podemos usar SQL dinámico o SPROCs para esas operaciones. Lo mejor es que el código que use nuestra capa de datos, y todas las reglas de negocio asociadas, serán las mismas sin importar que método de persistencia estemos usando. 
En futuros post veremos más conceptos sobre LINQ to SQL como: Herencia simple de tablas, Carga retrasada, concurrencia optimista, y administración de escenarios de N-capas. ESta semana estaré de vacaciones y espero tener más tiempo libre para escribir alguno de ellos.

Más contenido relacionado

PDF
Linq to sql 6
PDF
Linq to sql 3
PDF
Linq to sql 8
PDF
Linq to sql 4
PDF
Linq to sql 9
PDF
Manual Visual Basic .NET SQL Server paso a paso
PPTX
My Sql A C#
PDF
001 conexion-con-bd
Linq to sql 6
Linq to sql 3
Linq to sql 8
Linq to sql 4
Linq to sql 9
Manual Visual Basic .NET SQL Server paso a paso
My Sql A C#
001 conexion-con-bd

La actualidad más candente (19)

DOCX
la mejor forma de Conectar c# con mysql con archivos de configuracion
PDF
Introduccion a-linq..www.freelibros.com
DOCX
CONEXION VISUAL STUDIO.NET - SQL SERVER
PPT
Conexión a SQL Server con C#.NET a través de ODBC
PPTX
Aprenda a conectar sql y c# en 19 sencillos pasos!
PDF
Conexión de visual basic a bases de datos. María Parra
PPT
Conexión a sql server con c#
PDF
manual visual basic 02
DOCX
CREACION DE DLL Y USO (Ejemplo desarrollado)
PPTX
Bases de datos_angelina_monetti
PPTX
Conexión c# sql server
DOCX
Instituto tecnologico superior
PDF
Como conectar visual basic 6.0 a una base de datos microsoft sql server
PPTX
ConexióN De Una Base De Datos De Sql Con C#
PPTX
Curso SQL-C# Basico
PDF
Base datosvisualc#express2008
PDF
Cliente servidor
DOCX
Ejercicio basico en asp.net LOZADA ERICK
la mejor forma de Conectar c# con mysql con archivos de configuracion
Introduccion a-linq..www.freelibros.com
CONEXION VISUAL STUDIO.NET - SQL SERVER
Conexión a SQL Server con C#.NET a través de ODBC
Aprenda a conectar sql y c# en 19 sencillos pasos!
Conexión de visual basic a bases de datos. María Parra
Conexión a sql server con c#
manual visual basic 02
CREACION DE DLL Y USO (Ejemplo desarrollado)
Bases de datos_angelina_monetti
Conexión c# sql server
Instituto tecnologico superior
Como conectar visual basic 6.0 a una base de datos microsoft sql server
ConexióN De Una Base De Datos De Sql Con C#
Curso SQL-C# Basico
Base datosvisualc#express2008
Cliente servidor
Ejercicio basico en asp.net LOZADA ERICK
Publicidad

Similar a Linq to sql 7 (20)

PDF
Ejemplo Linq To SQL
PDF
Linq to sql 2
PDF
Linq to sql 5
PDF
Entity Framework ó Linq SQL - Visual Studio 2012
PDF
Buenas prácticas de codificación para capas de acceso a datos de aplicaciones...
PPTX
Programación con linq
PPTX
S8-DAW-2022S1.pptx
PDF
Orm final
PPT
Conceptos de hibernate
PDF
Linq En Visual Basic 2008
PPTX
PDF
Bdo r en oracle
PDF
Base de datos Objeto-Relacional.
PDF
MAPEO OBJETO RELACIONAL
PPTX
PDF
Modelos
Ejemplo Linq To SQL
Linq to sql 2
Linq to sql 5
Entity Framework ó Linq SQL - Visual Studio 2012
Buenas prácticas de codificación para capas de acceso a datos de aplicaciones...
Programación con linq
S8-DAW-2022S1.pptx
Orm final
Conceptos de hibernate
Linq En Visual Basic 2008
Bdo r en oracle
Base de datos Objeto-Relacional.
MAPEO OBJETO RELACIONAL
Modelos
Publicidad

Más de jcfarit (20)

PDF
Conceptos basicos de telefonia
PDF
Manual de usuario Ruani
PDF
Unidad 3 gestion de procesos en linux
PDF
Arquitectura General del Sistema Operativo Linux
PDF
ISO 27001 -6
PDF
ISO 27001 - 5
PDF
ISO 27001 4
PDF
ISO 27001 -3
PDF
ISO 27001
PDF
ISO 27001
PDF
Curso ubuntuimprimible
PDF
Curso ubuntu1extraimprimible
PDF
Autentificación-Firma Digital
DOC
Auditoría de Routers y Switches
DOC
Arquitectura multi agente.doc
RTF
Aplicaciones Criptográficas en Entornos Económicos
PDF
Análisis de los sistemas de dinero electrónico
DOC
Suneval
DOC
Guia plan de_clases
PPT
Los medios de enseñanza aprendizaje
Conceptos basicos de telefonia
Manual de usuario Ruani
Unidad 3 gestion de procesos en linux
Arquitectura General del Sistema Operativo Linux
ISO 27001 -6
ISO 27001 - 5
ISO 27001 4
ISO 27001 -3
ISO 27001
ISO 27001
Curso ubuntuimprimible
Curso ubuntu1extraimprimible
Autentificación-Firma Digital
Auditoría de Routers y Switches
Arquitectura multi agente.doc
Aplicaciones Criptográficas en Entornos Económicos
Análisis de los sistemas de dinero electrónico
Suneval
Guia plan de_clases
Los medios de enseñanza aprendizaje

Último (11)

PPTX
presentacion_energias_renovables_renovable_.pptx
PDF
[Ebook gratuito] Introducción a la IA Generativa, Instalación y Configuración...
PDF
Herramientaa de google google keep, maps.pdf
PDF
CAPACITACIÓN MIPIG - MODELO INTEGRADO DE PLANEACIÓN Y GESTIÓN
PPT
laser seguridad a la salud humana de piel y vision en laser clase 4
PPTX
Guia de power bi de cero a avanzado detallado
PDF
Mesopotamia y Egipto.pptx.pdf historia universal
PDF
Frases de Fidel Castro. Compilación Norelys Morales Aguilera
PPTX
FUNCIONES DE CLASSROOM EN EL FUNCIONAMIENTO ESCOLAR
PPTX
tema-2-interes-.pptx44444444444444444444
PPTX
Presentación de un estudio de empresa pp
presentacion_energias_renovables_renovable_.pptx
[Ebook gratuito] Introducción a la IA Generativa, Instalación y Configuración...
Herramientaa de google google keep, maps.pdf
CAPACITACIÓN MIPIG - MODELO INTEGRADO DE PLANEACIÓN Y GESTIÓN
laser seguridad a la salud humana de piel y vision en laser clase 4
Guia de power bi de cero a avanzado detallado
Mesopotamia y Egipto.pptx.pdf historia universal
Frases de Fidel Castro. Compilación Norelys Morales Aguilera
FUNCIONES DE CLASSROOM EN EL FUNCIONAMIENTO ESCOLAR
tema-2-interes-.pptx44444444444444444444
Presentación de un estudio de empresa pp

Linq to sql 7

  • 1. LINQ to SLQ (Parte 7 – Actualizando la base de datos con procedimientos almacenados) 9 respuestas En las últimas semanas he escrito una serie de post sobre LINQ to SQL. Es un ORM integrado en .NET 3.5, y nos permite modelar bases de datos relacionales con clases de .NET. Podemos usar expresiones LINQ para consultar a la base de datos, actualiazarla, insertar y borrar datos. Aquí tenéis los enlaces a los otros post:  Parte 1: Introducción a LINQ to SQL  Parte 2: Definiendo el modelo de datos.  Parte 3: Consultando la base de datos  Parte 4: Actualizando la base de datos.  Parte 5: Enlazar controles de interfaz de usuario con el ASP:LinqDatSource  Parte 6: Obtener datos con procedimientos almacenados. En la sexta parte vimos cómo podemos usar procedimientos almacenados (SPROCs) y funciones definidas por el usuario (UDFs) para consultar la base de datos con el modelo de datos de LINQ to SQL. En el post de hoy veremos cómo podemos usar los SPROCs para actualizar/insertar/borrar datos de nuestra base de datos. Para ayudar a entender esto empezaremos costruyendo una capa de datos para la base de datos de ejemplo Northwind: Paso 1: Crear nuestra capa de acceso a datos (sin SPROCs) En la segunda parte de esta serie vimos cómo usar el diseñador de LINQ to SQL de VS 2008 para crear el siguiente modelo de clases:
  • 2. Añadiendo reglas de validación a nuestro modelo de clases. Después de definir nuestro modelo querremos añadir reglas de validación a nuestro modelo de datos. Podemos hacer esto añadiendo clases parciales a nuestro proyecto y añadir las reglas de validación en esas clases (vimos cómo hacer esto en la cuarta parte de esta serie). Por ejemplo, podemos añadir la lógica necesaria para asegurarnos de que el número de teléfono de los clientes siguen un patrón válido, y otra para asegurarnos de que la fecha de entrega (RequierdDate) es posterior a la fecha actual del pedido (OrderDate). Una vez que hemos definido las clases parciales, estos métodos de validación se ejecutarán cada vez que escribamos código para actualizar nuestros objetos de datos de nuestra aplicación: VB:
  • 3. C#:
  • 4. Añadir un método de ayuda GetCustomer() a nuestro DataContext Una vez que hemos creado nuestro modelo de clases, y que le hemos añadido reglas de validación, podemos consultar e interactuar con los datos. Podemos hacer esto escribiendo expresiones LINQ sobre nuestro modelo de clases (vimos cómo hacer esto en la tercera parte de esta serie). También podemos mapear SPROCs en nuestro DataContext (esto lo vimos en la sexta parte de la serie). Cuando creamos una capa de datos con LINQ to SQL normalmente querremos encapsular consultas comunes de LINQ (o SPROCs) en métodos auxiliares que añadiremos a la clase DataContext. Esto lo conseguimos añadiendo una clase parcial a nuestro proyecto. Por ejemplo, podemos añadir un método llamado "GetCustomer()" que nos permita buscar y obtener objetos Customer de la base de datos a partir del valor CustomerID: VB:
  • 5. C#: Paso 2: Usando nuestra capa de datos (seguimos sin SPROCs) Ya tenemos una capa de datos que encapsula nuestro modelo de datos, integra reglas de validación, y nos permite consultar, actualizar, insertar y borrar datos. Veamos ahora un escenario simple usándolo para obtener un objeto customer existente, actualizamos el ContactName y el PhoneNumber, y creamos un nuevo objeto Order para asociarlos. El siguiente código hace todo eso en una sola transacción. LINQ to SQL se asegura de que las reglas de validación se cumplen ántes de guardar nada en la base de datos: VB:
  • 6. C#: LINQ to SQL monitoriza todas las modificaciones de los objetos que hemos obtenido de la base de datos, y guarda los objetos que añadimos. Cuando llamamos al método DataContext.SubmitChanges(), LINQ to SQL comprueba las reglas que hemos establecido, y genera automáticamente la SQL que actualizará el registro de Customer e insertará un nuevo registro en la tabla Orders Un momento - Pensaba que este post iba sobre SPROCs Si aún estais leyendo, os preguntaréis dónde están los SPROCs en este post. ¿Porque os estoy mostrando el código de arriba que hace que se genere una SQL dinámica? ¿Por qué no os he enseñado cómo llamar a un SPROC para hacer las inserciones/actualizaciones/borrados todavía? La razón es que el modelo de programación de LINQ to SQL tanto para trabajar con objetos modelados mediante SPROC es exactamente el mismo que con SQL dinámico. La manera en que añadimos validación lógica es exactamente igual (así que todas las reglas que hemos añadido a nuestro modelo de datos se aplicarán también si usamos SPROCs). El código anterior que hemos usado para obtener un cliente, actualizarlo y añadir un nuevo pedido es exactamente igual tanto si usamos SQL dinámico como si usamos SPROCs.
  • 7. Esta simetría en el modelo de programación es muy potente ya que no tenemos que aprender dos maneras diferentes de hacer las cosas, ni tenemos que decidir al principio del proyecto qué técnica usar, si SPROC o no. Podemos empezar usando el SQL dinámico que nos da LINQ to SQL para las consultas, inserciones, actualizaciones y borrados. Podemos añadir reglas de validación a nuestro modelo. Y luego podemos actualizar el modelo de datos para usar SPROCs - o no. El código y los test que escribamos contra las clases del modelo de datos serán exáctamente iguales. De ahora en adelante veremos cómo podemos actualizar nuestro modelo de datos usando SPROCs para actualizar/insertar/borrar - mientras seguimos usando las mismas reglas de validación y trabajaremos con los mismos códigos anteriores. Cómo usar SPROCs en inserciones, actualizaciones y borrados Podemos modificar la capa de datos que estamos construyendo para que use SPROCs, en lugar de SQL dinámico de dos maneras: 1. Usando el diseñador de LINQ to SQL para configurar gráficamente la ejecución de los SPROCs en las diferentes operaciones o 2. Añadir una clase parcial NorthwindDataContext a nuestro proyecto, y entonces implementar los métodos necesarios para la inserción, borrado y actualización. (por ejemplo: InsertOrder, UpdateOrder, DeleteOrder) que serán llamados cuando se realize alguna de las operaciones asociadas. Estos métodos parciales serán pasados a las instancias del modelo de datos que queramos actualizar, y podemos ejecutar tanto SPROC como código SQL para guardarlo. Cuando usemos la primera aproximación para configurar gráficamente los SPROCs que llamaremos, por debajo se está generando el mismo código (en clases parciales que crea él solo) que escribiríamos si elegimos la segunda opción. En general os recomiendo que uséis el diseñador de LINQ to SQL para configurar los SPROCs en el 90% de los casos - y crear las llamadas personalizadas a procedimientos almacenados en escenarios más avanzados. Paso 3: Hacer otras inserciones con un SPROC Empezaremos cambiando nuestro modelo de datos para que use SPROCs con el objeto Order. Primero nos vamos a la ventana de "Explorador de Servidores" (Server Explorer) de Visual Studio, expandimos el nodo "Stored Procedures" de nuestra base de datos, hacemos clic con el botón derecho y elegimos la opción "Add New Stored Procedure": Creamos el nuevo procedimiento almacenado que llamaremos "InsertOrder" que añade una nueva fila order a la tabla Orders:
  • 8. Fijáos que hemos definido el parámetro "OrderId" como un parámetro de salida. ESto es debido a que la columna OrderID es una columna identidad que se autoincrementa cada vez que se añade un nuevo registro. Quien llame a este SPROC deverá pasarle un valor null en ese parámetro - y el SPROC devolverá en ese parámetro el nuevo valor OrderID (llamando a la función SCOPE_IDENTITY() al final del SPROC). Después de crear el SPROC abrimos el diseñador de LINQ to SQL. De la misma forma que vimos en la sexta parte de esta serie, podemos arrastrar y soltar SPROCs desde la ventana "server explorer" al diseñador. Esto es lo que haremos con el nuevo SPROC que acabamos de crear:
  • 9. El último paso será decirle a nuestra capa de datos que use el SPROC InsertOrder cuano inserter un nuevo objeto Order en la base de datos. Esto lo hacemos seleccionando la clase "Order" del diseñador LINQ to SQL, y en las propiedades clicamos el botón "..." del método Insert: Hacemos clic en el botón "..." y aparecerá una ventana que nos permite personalizar las operaciones de inserción:
  • 10. Fijaos cómo el modo po defecto ("Use Runtime") está configurado para usar LINQ to SQL como generador dinámico de las SQL. Para cambiarlo seleccionamos el radio buton "Customize" y seleccionamos el SPROC InsertOrder de la lista de SPROCS disponibles: El diseñador de LINQ to SQL calculará una lista de parametros para el SPROC que hemos seleccionado, permitiéndonos mapear las propiedades de nuestra clase Order a los parámetros del SPROC InsertOrder. Por defecto seleccionará el que más se parezca en el nombre. Podemos cambiarlo si queremos.
  • 11. Una vez que cliquemos en OK está listo. Ahora cada vez que añadamos un nuevo pedido a nuestro DataContext e invoquemos al método SubmitChanges(), se ejecutará el SPROC InsertOrder. Importante: Aunque estemos usando SPROC para la persistencia, el método parcial "OnValidate()" que creamos (en la primer parte de esta serie) para encapsular las reglas de validación para los pedidos seguirán ejecutándose antes de realizar cualquier cambio. Es decir, tenemos una forma limpia de encapsular la lógica de negocio y las reglas de validación en nuestros modelos de datos, y podemos reutilizarlos tanto si usamos SQL o SPROCS. Paso 4: Actualizando los clientes con SPROCs. Ahora vamos a modificar el objeto Customer para manejar las actualizaciones con un SPROC. Empezamos creando el SPROC "UpdateCustomer": Fijaos que además de pasar el parámetro @CustomerID, también tenemos un parámetro @Original_CustomerID. La columna CustomerID de la tabla Customers no es un campo autoincremental, y puede modificarse cuando hagamos una actualización. Por tanto necesitamos ser capaces de decirle al SPROC cual es el CustomerID original y el nuevo CustomerID. Vamos a ver cómo mapeamos esto con el diseñador de LINQ to SQL. Veréis que estamos pasando un parámetro llamado @Version (que es una marca de tiempo) al SPROC. Es una nueva columna que he añadido a la tabla Customers para ayudarme a controlar la concurrencia optimista. Veremos en más detalle este tema en otro post de esta serie - pero en resumen es que LINQ to SQL soporta completamente la concurrencia optimista, y nos permite usar tanto una marca de tiempo o usar valores original/nuevo para detectar si ha habido algún cambio por parte de otro usuario ántes de guardar los datos. Para este ejemplo usaremos una marca de tiempo ya que hace que el código sea mucho más claro. Una vez que tenemos nuestro SPROC, lo arrastramos y soltamos al diseñador LINQ to SQL para añadirlo como método a nuestro DataContext. Seleccionamos la clase Customer y hacemos clic en el botón "..." de la propiedad Update:
  • 12. Seleccionamos el radio button "Customize" y seleccionamos el SPROC UpdateCustomer: Cuando mapeamos las propiedades de los objetos Customer con los parámetros del SPROC, veremos que tenemos que decidir si poner la propiedad "current" en el objeto de datos, o si poner el valor original que estaba en la base de datos antes de obtener el objeto. Por ejemplo, tendremos que asegurarnos de que mapeamos el valor "current" de la propiedad CustomerID en el parámetro @CustomerID, y el valor original en el parámetro @original_customerID.
  • 13. Cuando hacemos clic en OK ya esta terminado. Ahora cuando actualizemos cualquier cliente y llamemos a SubmitChanges() se ejectuará el SPROC UpdateCustomer en lugar de ejecutarse un SQL dinámico. Importante: Aunque ahora estemos usando SPROC, el método parcial "OnPhoneChanging()" de la clase Customer (que creamos en el primer post de esta serie) para validar los números de teléfono se seguirá ejecutando de la misma manera ántes de que se guarden los cambios. Tenemos de esta forma una forma limpia de encapsular reglas de negocio y validación a nuestros modelos de datos, y podemos reutilizarlos tanto si usamos SQL dinámico o SPROCs. Paso 5: Usando el modelo de datos otra vez (esta vez con SPROCs) Ahora que ya tenemos configurada nuestra capa de datos para usar SPOCs en lugar de SQL dinámico, podemos ejecutar el mismo código que vimos en el paso 2: Ahora las actualizacion del objeto Customer, y la inserción del objeto ORder, se están ejecutando a través de SPROCs en lugar de SQL dinámico. La lógica de validación que definimos se siguen ejecutando como antes, y el código sigue siendo exactamente el mismo. Apuntes avanzados cuando usamos SPROCs Veamos unas cuantas recomendaciones útiles para escenarios con SPROC más avanzados con LINQ to SQL Uso de parámetros de salida En casos de inserción (Paso 3) hemos visto cómo podemos devolver el nuevo valor OrderID (que es un valor identidad y autoincremental de la tabla Orders) usando un parámetro de salida en el SPROC. No estamos limitados a devolver sólo valores de columnas identidad con SPROCs y LINQ to SQL - en realidad podemos actualizar y devolver cualquier parámetro. Podemos usarlo tanto para insetar como para actualizar. LINQ to SQL tomará el valor resultado y actualizará la propiedad asociada en el modelo de dato sin que tengamos que hacer ninguna consulta extra para refrescarlo o calcularlo de nuevo. ¿Que pasa si el SPROC da un error? Si el SPROC da un error mientras inserta, actualiza o borra un dato, LINQ to SQL cancelará y deshará la transacción de todos los cambios asociados a la llamada SubmitChanges(). De manera que nos aseguramos la consistencia de los datos. ¿Podemos escribir código en lugar de usar el diseñador para llamar a un SPROC? Como ya comenté al principio, podemos usar tanto el diseñador de LINQ to SQL para mapear las operaciones con SPROC o podemos añadir métodos parciales a la clase DataContext programáticamente e invocarlos nosotros mismo.
  • 14. Aquí tenéis un ejemplo del código que deberíamos escribir para sobreescribir el método UpdateCustomer de la clase NorthwindDataContext: Este código es el que fué generado con el diseñador de LINQ to SQL cuando lo usamos para mapear el SPROC y asociarlo a la operación de Update del objeto Customer. Podemos usarlo como un punto de partida y añadir alguna lógica adicional para hacerlo más personalizado (por ejemplo: usar el valor de retorno del SPROC para lanzar excepciones personalizadas). Resumen LINQ to SQL es un ORM muy flexible. Nos permite escribir código limpio orientado a objetos para obtener, acutalizar e insertar datos. Lo mejor de todo es que nos permite diseñar una capa de datos realmente limpia e independiente de cómo se guardan y cargan los datos de la base de datos. Podemos usar SQL dinámico o SPROCs para esas operaciones. Lo mejor es que el código que use nuestra capa de datos, y todas las reglas de negocio asociadas, serán las mismas sin importar que método de persistencia estemos usando. En futuros post veremos más conceptos sobre LINQ to SQL como: Herencia simple de tablas, Carga retrasada, concurrencia optimista, y administración de escenarios de N-capas. ESta semana estaré de vacaciones y espero tener más tiempo libre para escribir alguno de ellos.