{"id":3625,"date":"2013-03-06T21:00:58","date_gmt":"2013-03-06T20:00:58","guid":{"rendered":"http:\/\/www.palentino.es\/blog\/?p=3625"},"modified":"2013-03-07T11:22:16","modified_gmt":"2013-03-07T10:22:16","slug":"nhibernate-mi-primera-aplicacion-orm-caso-practico","status":"publish","type":"post","link":"https:\/\/www.palentino.es\/blog\/nhibernate-mi-primera-aplicacion-orm-caso-practico\/","title":{"rendered":"NHibernate, mi primera aplicaci\u00f3n ORM, caso pr\u00e1ctico."},"content":{"rendered":"<p style=\"text-align: justify;\">Un ORM es una t\u00e9cnica-software para convertir\u00a0<strong>datos orientados a objetos a una base de datos relacional<\/strong>, usando un motor de persistencia. Se crea una base de datos orientada a objetos\u00a0<strong>virtual<\/strong>\u00a0sobre una base de datos relacional. \u00a0Por lo tanto su principal ventaja es &#8220;olvidarse&#8221; de la tediosa labor e crear todas las sentencias SQL para obtener,actualizar, insertar o borrar datos (CRUD como veremos adelante) en la base, as\u00ed como soporte para la persistencia.<\/p>\n<p>Existen dos\u00a0alternativas entre otras &#8230;<\/p>\n<p><span style=\"color: #800000;\"><strong>Hibernate<\/strong> <\/span>es una herramienta <strong>ORM<\/strong> (Object-Relational Mapping) \u00f3 Mapeo Objeto Relacional para la plataforma <strong>JAVA<\/strong>.<\/p>\n<p style=\"text-align: justify;\"><span style=\"color: #000080;\"><strong>NHibernate<\/strong> <\/span>es la\u00a0alternativa de software\u00a0libre disponible para <strong>.NET en C#,<\/strong> distribuido bajo los t\u00e9rmimos<strong> LGPL<\/strong>. Es una de las primeras aproximaciones para el mundo .NET de proyectos ORM, a la cual se ha unido Microsoft con LinqToSQL y Entity Framework.<\/p>\n<p style=\"text-align: justify;\">Vamos a tratar NHibernate.\u00a0Al emplearle para el acceso a datos, el desarrollador\u00a0garantiza\u00a0que su aplicaci\u00f3n es <strong>independiente<\/strong> en cuanto al motor de datos empleado en producci\u00f3n. \u00a0Soporta los SGBDR <strong>m\u00e1s empleados<\/strong> en el mercado como puede ser MYSQL, Postgre, Oracle, MSSQL, etc. S\u00f3lo es necesario cambiar una <strong>l\u00ednea en el fichero de configuraci\u00f3n para que podamos emplear una base de datos distinta.<\/strong><\/p>\n<p style=\"text-align: justify;\">NHiberbate facilita el mapeo de atributos entre una base de datos relacional tradicional y el modelo de objetos de una aplicaci\u00f3n, mediante <strong>archivos declarativos (XML)<\/strong> que permiten establecer estas relaciones. Intenta solucionar el problema de la diferencia entre los 2 modelos usados hoy en d\u00eda para organizar y manipular datos:\u00a0El usado en la memoria del ordenador (orientaci\u00f3n a objetos) y el usado en los sistemas gestores bases de datos (modelo relacional).<\/p>\n<p style=\"text-align: justify;\">Para lograrlo permite al desarrollador especificar <strong>c\u00f3mo<\/strong> es su modelo de datos, <strong>qu\u00e9<\/strong> relaciones existen y qu\u00e9 <strong>forma<\/strong> tienen. Con esta informaci\u00f3n NHibernate le permite a la aplicaci\u00f3n manipular los datos de la base operando sobre objetos, con todas las caracter\u00edsticas de la POO.<\/p>\n<p style=\"text-align: justify;\">Hibernate convertir\u00e1 los datos entre los tipos utilizados por c# y los definidos por SQL.<strong> Hibernate genera las sentencias SQL<\/strong> y<strong> libera al desarrollador del manejo manual de los datos<\/strong> que resultan de la ejecuci\u00f3n de dichas sentencias, manteniendo la <strong>portabilidad<\/strong> entre todas las bases de datos con un <strong>ligero incremento en el tiempo de ejecuci\u00f3n<\/strong>.<\/p>\n<p style=\"text-align: justify;\">NHibernate est\u00e1 dise\u00f1ado para ser flexible en cuanto al esquema de tablas utilizado, para poder adaptarse a su uso sobre una base de datos ya existente. Tambi\u00e9n tiene la funcionalidad de crear la base de datos a partir de la informaci\u00f3n disponible.<\/p>\n<p style=\"text-align: justify;\">Posee tambi\u00e9n un lenguaje de consulta de datos llamado <strong>HQL<\/strong> (Hibernate Query Language), al mismo tiempo que una API para construir las consultas de forma programada (conocida como &#8220;<strong>criteria<\/strong>&#8220;).<\/p>\n<p>Trabajemos un poco con \u00e9l. La versi\u00f3n que he empleado es la\u00a0<a href=\"http:\/\/sourceforge.net\/projects\/nhibernate\/files\/NHibernate\/3.3.1GA\/NHibernate-3.3.1.GA-bin.zip\/download\" target=\"_blank\"><strong>NH3.3.1<\/strong><\/a><\/p>\n<p><strong>Nada de hibernar y ;-), manos a la obra.<\/strong><!--more--><\/p>\n<p><a href=\"http:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/nhibernate-logotipo.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-3633\" alt=\"nhibernate-logotipo\" src=\"http:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/nhibernate-logotipo-300x112.png\" width=\"300\" height=\"112\" srcset=\"https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/nhibernate-logotipo-300x112.png 300w, https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/nhibernate-logotipo.png 600w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Aspectos a tratar en el taller, caso pr\u00e1ctico&#8230;<\/p>\n<ul>\n<li>Instalaci\u00f3n.<\/li>\n<li>Definiremos una clase de negocio sencilla.<\/li>\n<li>Crearemos un mapeo para leer y grabar el objeto de negocio.<\/li>\n<li>Configuraremos NHhibernate para interacturar con la base de datos local.<\/li>\n<li style=\"text-align: justify;\">Escribiremos c\u00f3digo <strong>CRUD<\/strong> usando el\u00a0patr\u00f3n\u00a0del repositorio. \u00a0En computaci\u00f3n CRUD es el acr\u00f3nimo de Crear, Obtener, Actualizar y Borrar (del original en ingl\u00e9s: Create, Read, Update and Delete). Es usado para referirse a las funciones b\u00e1sicas en bases de datos o la capa de persistencia en un software.<\/li>\n<li style=\"text-align: justify;\">Realizaremos pruebas unitarias para asegurarnos que el c\u00f3digo trabaja correctamente.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\"><strong>Instalaci\u00f3n, primer paso.<\/strong><\/p>\n<p style=\"text-align: justify;\">Como he podido comprobar, NHibernate se puede usar desde Visual Studio, al crear una nueva soluci\u00f3n. En esa soluci\u00f3n se agrega una biblioteca de clases\u00a0d\u00e1ndole\u00a0el nombre de Nhibertante. En forma de dll o componente para ser agregado <strong>como referencia<\/strong>. Son un conjunto de dlls.\u00a0Es necesario relacionar tablas con clases.<\/p>\n<p style=\"text-align: justify;\">Grosso Modo, a trav\u00e9s de un fichero .xml, se codifica la configuraci\u00f3n de acceso a la base. Se indican las tablas y campos afectados. En el <strong>web.config<\/strong> se establecen las bases de datos con las que trabajar.Para manipular datos, se crean sesiones nhsession en las clases.<\/p>\n<p style=\"text-align: justify;\"><a href=\"http:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/Nhibernate-esquema.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3635\" alt=\"Nhibernate-esquema\" src=\"http:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/Nhibernate-esquema.png\" width=\"389\" height=\"477\" srcset=\"https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/Nhibernate-esquema.png 389w, https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/Nhibernate-esquema-244x300.png 244w\" sizes=\"auto, (max-width: 389px) 100vw, 389px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Generar esta estructura es nuestro objetivo.<\/p>\n<p style=\"text-align: justify;\"><a href=\"http:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/solutionex.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3641\" alt=\"solutionex\" src=\"http:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/solutionex.png\" width=\"313\" height=\"310\" srcset=\"https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/solutionex.png 313w, https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/solutionex-150x150.png 150w, https:\/\/www.palentino.es\/blog\/wp-content\/uploads\/2013\/03\/solutionex-300x297.png 300w\" sizes=\"auto, (max-width: 313px) 100vw, 313px\" \/><\/a><\/p>\n<p><!--more--><\/p>\n<p style=\"text-align: justify;\">La p\u00e1gina oficial es <a href=\"http:\/\/nhforge.org\/\" target=\"_blank\">http:\/\/nhforge.org\/<\/a><\/p>\n<p style=\"text-align: justify;\">Lo primero que tenemos que hacer es descomprimir el archivo zip descargado. \u00a0El fichero puedes\u00a0baj\u00e1rtelo\u00a0desde <a href=\"http:\/\/sourceforge.net\/projects\/nhibernate\/files\/NHibernate\/3.3.1GA\/NHibernate-3.3.1.GA-bin.zip\/download\" target=\"_blank\">aqu\u00ed<\/a>. Al hacerlo se crea generalmente una carpeta c:\\code\\sharelibs\\Nhibernate, aunque puedes darle otra ruta.<\/p>\n<p style=\"text-align: justify;\">La carpeta Sharelibs es la que necesitaremos para a\u00f1adir la referencia y dlls, desde Visual Studio. As\u00ed de simple. En funci\u00f3n de la\u00a0versi\u00f3n\u00a0del IDE donde nos encontremos, no obstante funciona perfectamente con VS 2008 y Framework .NET 3.5<\/p>\n<p style=\"text-align: justify;\">Existen alternativas para automatizar la descarga desde Visual Studio, sin necesidad de salir del IDE. Una de ellas es \u00a0<a href=\"http:\/\/nuget.org\/\" target=\"_blank\">NuGet<\/a>. Nuget es una extensi\u00f3n para Visual studio, para agregar\u00a0third-party y tools al VS.<\/p>\n<p style=\"text-align: justify;\">Antes de comenzar a construir nuestra aplicaci\u00f3n y los objetos de negocio, necesitaremos crear un proyecto en blanco. Es necesario abrir VS y crear un proyecto\u00a0librer\u00eda\u00a0de clases o class library. \u00a0Es en este punto cuando veremos algo interesante, crear objetos de negocio.<\/p>\n<p style=\"text-align: justify;\">He descubierto varios v\u00eddeos\u00a0en castellano, sobre el trabajo con Visual Studio 2010, por si deseamos aprender este proceso de forma visual.<\/p>\n<p><a href=\"http:\/\/www.youtube.com\/watch?v=5FxrwWBj_os\" target=\"_blank\">Parte 1<\/a> , <a href=\"http:\/\/www.youtube.com\/watch?v=kAKRVnJdP0k\" target=\"_blank\">Parte 2<\/a><\/p>\n<p><strong>Definiremos una clase de negocio sencilla. Los objetos de negocio.<\/strong><\/p>\n<p>Comencemos definiendo un simple dominio. Por el momento consiste en una entidad llamada Producto. El producto tiene 3 propiedades. Nombre, categor\u00eda y SinCatalogar (discontinued).<\/p>\n<p><img decoding=\"async\" class=\"aligncenter\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/ProductDef.png\" \/><\/p>\n<p style=\"text-align: justify;\">Es necesario crear una carpeta Domain (Dominio) dentro del proyecto soluci\u00f3n en VS. \u00a0Dentro de esta carpeta crearemos una clases llamada product.cs (producto). El c\u00f3digo es muy sencillo y usa propiedades autom\u00e1ticas (una nueva caracter\u00edstica del compilador de C# 3.0)<\/p>\n<pre style=\"border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 700px; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4;\"><span style=\"color: #0000ff;\">namespace<\/span> FirstSolution.Domain\r\n{\r\n    <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">class<\/span> Producto\r\n    {\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">string<\/span> nombre { get; set; }\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">string<\/span> Categoria { get; set; }\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">bool<\/span> SinCatalogar { get; set; }\r\n    }\r\n}<\/pre>\n<p style=\"text-align: justify;\">Ahora queremos se capaces de almacenar de forma persistente instancias de esta entidad en una base de datos relacional. \u00bfEs el objetivo no?, para eso usamos NHibernate. Una instancia de una entidad en un dominio de aplicaci\u00f3n tiene correspondencia con una fila en una tabla de la base de datos. Esto es un dato importante. Por lo tanto, tendremos que definir un mapeo entre la entidad y la correspondiente tabla en la base de datos. Este mapeo puede ser realizado de varias formas, definiendo un fichero de mapeo o mapping en forma de documento xml o decorando la entidad con atributos. Comencemos con el mapeo del fichero.<\/p>\n<p style=\"text-align: justify;\"><strong>Crearemos un mapeo para leer y grabar el objeto de negocio. Definiendo el Mapping o mapeo.<\/strong><\/p>\n<p style=\"text-align: justify;\">Crearemos otra carpeta llamada Mappings en el proyecto. Crearemos un nuevo documento xml en esta carpeta y lo llamaremos producto.hbm.xml. Como podemos apreciar, &#8220;hbm&#8221; es parte del nombre del fichero. \u00a0Esta nomenclatura o convenci\u00f3n es usada por NHibernate para reconocer autom\u00e1ticamente el fichero de tipo mapeo. Es necesario definir este fichero xml como &#8220;Recurso embebido&#8221;.<\/p>\n<p style=\"text-align: justify;\">En el explorador de Windows localiza el<strong> nhibenate-mapping.xsd<\/strong>\u00a0en la carpeta del\u00a0c\u00f3digo\u00a0fuente de NHibernate y c\u00f3piala en tu carpeta Sharedlibs. \u00a0Ahora podemos usar este fichero de\u00a0definici\u00f3n\u00a0de esquema xml cuando definamos nuestros ficheros de mapeo. Visual Studio te ofrecer\u00e1 ayuda intelsense y validacion cuando edites el documento xml de mapeo.<\/p>\n<p style=\"text-align: justify;\">Vuelve a VS y a\u00f1ade el esquema a el fichero producto.hbm.xml como muestra la imagen inferior.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/properties.png\" \/><\/p>\n<p style=\"text-align: justify;\">Comencemos ahora. Cada fichero de mapeo tiene que definir un nodo\u00a0ra\u00edz\u00a0o root. Se puede apreciar en &lt;hibernate-mapping&gt;<\/p>\n<pre style=\"text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 700px; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4;\"><span style=\"color: #0000ff;\">&lt;?<\/span><span style=\"color: #800000;\">xml<\/span> <span style=\"color: #ff0000;\">version<\/span><span style=\"color: #0000ff;\">=\"1.0\"<\/span> <span style=\"color: #ff0000;\">encoding<\/span><span style=\"color: #0000ff;\">=\"utf-8\"<\/span> ?<span style=\"color: #0000ff;\">&gt;<\/span>\r\n<span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">hibernate-mapping<\/span> <span style=\"color: #ff0000;\">xmlns<\/span><span style=\"color: #0000ff;\">=\"urn:nhibernate-mapping-2.2\"<\/span> \r\n                   <span style=\"color: #ff0000;\">assembly<\/span><span style=\"color: #0000ff;\">=\"FirstSolution\"<\/span> \r\n                   <span style=\"color: #ff0000;\">namespace<\/span><span style=\"color: #0000ff;\">=\"FirstSolution.Domain\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n\r\n  <span style=\"color: #008000;\">&lt;!-- more mapping info here --&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">hibernate-mapping<\/span><span style=\"color: #0000ff;\">&gt;<\/span><\/pre>\n<p style=\"text-align: justify;\">En un fichero de mapeo cuando se referencia a una clase del dominio de \u00a0aplicaci\u00f3n, siempre tendr\u00e1s que proporcinar un FQN o nombre de acceso completo a la clase. Ejemplo: Primerejemplo.Domain.Producto.<\/p>\n<p style=\"text-align: justify;\">Para hacer que el fichero xml sea menos detallado o complejo puedes definir un nombre de ensamblado (en este caso las clases del dominio de aplicaci\u00f3n\u00a0est\u00e1n\u00a0implementadas y el namespace de las clases del dominio se componen de dos atributos, ensamblado y namespace del nodo\u00a0ra\u00edz. Es similar a usar una instrucci\u00f3n o estamento en C#.<\/p>\n<p style=\"text-align: justify;\">Volviendo a la clase, Ahora primero tendremos que definir una clave primaria para la entidad producto. T\u00e9cnicamente nosotros\u00a0podr\u00edamos\u00a0dejar el nombre como clave, pero es aconsejable subrogar la clave. A\u00f1adiremos una propiedad a la clase y la llamaremos id. Usaremos Guid como tipo de id, pero tambi\u00e9n puede definirse como int o long.<\/p>\n<p style=\"text-align: justify;\">As\u00ed es como queda la clase (lo dejo a partir de ahora en ingl\u00e9s que es como viene en la ayuda).<\/p>\n<pre style=\"text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 700px; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4;\"><span style=\"color: #0000ff;\">using<\/span> System;\r\n\r\n<span style=\"color: #0000ff;\">namespace<\/span> FirstSolution.Domain\r\n{\r\n    <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">class<\/span> Product\r\n    {\r\n        <span style=\"color: #0000ff;\">public<\/span> Guid Id { get; set; }\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">string<\/span> Name { get; set; }\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">string<\/span> Category { get; set; }\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">bool<\/span> Discontinued { get; set; }\r\n    }\r\n}<\/pre>\n<p style=\"text-align: justify;\">Podemos apreciar que hemos agregado el Guid id.<\/p>\n<p style=\"text-align: justify;\">Ahora veamos como ha quedado el fichero de mapeo.<\/p>\n<pre style=\"text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 700px; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4;\"><span style=\"color: #0000ff;\">&lt;?<\/span><span style=\"color: #800000;\">xml<\/span> <span style=\"color: #ff0000;\">version<\/span><span style=\"color: #0000ff;\">=\"1.0\"<\/span> <span style=\"color: #ff0000;\">encoding<\/span><span style=\"color: #0000ff;\">=\"utf-8\"<\/span> ?<span style=\"color: #0000ff;\">&gt;<\/span>\r\n<span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">hibernate-mapping<\/span> <span style=\"color: #ff0000;\">xmlns<\/span><span style=\"color: #0000ff;\">=\"urn:nhibernate-mapping-2.2\"<\/span> \r\n                   <span style=\"color: #ff0000;\">assembly<\/span><span style=\"color: #0000ff;\">=\"FirstSolution\"<\/span> \r\n                   <span style=\"color: #ff0000;\">namespace<\/span><span style=\"color: #0000ff;\">=\"FirstSolution.Domain\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n\r\n  <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">class<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"Product\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n    <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">id<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"Id\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n      <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">generator<\/span> <span style=\"color: #ff0000;\">class<\/span><span style=\"color: #0000ff;\">=\"guid\"<\/span> <span style=\"color: #0000ff;\">\/&gt;<\/span>\r\n    <span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">id<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n    <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">property<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"Name\"<\/span> <span style=\"color: #0000ff;\">\/&gt;<\/span>\r\n    <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">property<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"Category\"<\/span> <span style=\"color: #0000ff;\">\/&gt;<\/span>\r\n    <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">property<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"Discontinued\"<\/span> <span style=\"color: #0000ff;\">\/&gt;<\/span>\r\n  <span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">class<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">hibernate-mapping<\/span><span style=\"color: #0000ff;\">&gt;<\/span><\/pre>\n<p style=\"text-align: justify;\">Vemos como se han agregado las propiedades de la clase en forma de atributos xml.<\/p>\n<p style=\"text-align: justify;\">Sigamos&#8230;<\/p>\n<p style=\"text-align: justify;\">NHibernate no nos entorpece a intentar definir algunos valores razonables por defecto. Es decir, si no proporcionamos nombres de comumnas se definen automaticamente en base a la propiedad.<\/p>\n<p style=\"text-align: justify;\">Nuestro explorador de soluciones en Visual Studio (VS) deber\u00e1 ahora tener este aspecto (Domanin.cd contiene el diagrama de clases). Tendremos que haber a\u00f1adido la carpeta de dise\u00f1o y creado el diagrama de clases nosotros mismos, aunque esto es solo una buena costumbre y no es necesario para este caso pr\u00e1ctico.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/solutionex.png\" \/><\/p>\n<p style=\"text-align: justify;\">Vayamos ahora al siguiente punto a tratar.<\/p>\n<p style=\"text-align: justify;\"><strong>Configurar NHibertante.<\/strong><\/p>\n<p style=\"text-align: justify;\">Ahora tenemos que decirle a HHibernate que producto gestor de datos queremos usar y proporcionar en forma de cadena de conexion (connection string). NHibernate soporta muchos gestores de bases de datos.<\/p>\n<p style=\"text-align: justify;\">A\u00f1ade un nuevo fichero xml a la soluci\u00f3n(proyecto) y llamalo hibernate.cfg.xml. Establece sus propiedades a &#8220;Copy to Output&#8221; y &#8220;Copy always&#8221;. \u00a0Usando SQL Server Compact Edition , es este taller introduciremos la siguiente informaci\u00f3n dentro del fichero xml.<\/p>\n<pre style=\"text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 700px; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4;\"><span style=\"color: #0000ff;\">&lt;?<\/span><span style=\"color: #800000;\">xml<\/span> <span style=\"color: #ff0000;\">version<\/span><span style=\"color: #0000ff;\">=\"1.0\"<\/span> <span style=\"color: #ff0000;\">encoding<\/span><span style=\"color: #0000ff;\">=\"utf-8\"<\/span> ?<span style=\"color: #0000ff;\">&gt;<\/span>\r\n<span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">hibernate-configuration<\/span> <span style=\"color: #ff0000;\">xmlns<\/span><span style=\"color: #0000ff;\">=\"urn:nhibernate-configuration-2.2\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n  <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">session-factory<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n    <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">property<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"connection.provider\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>NHibernate.Connection.DriverConnectionProvider<span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">property<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n    <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">property<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"dialect\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>NHibernate.Dialect.MsSqlCeDialect<span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">property<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n    <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">property<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"connection.driver_class\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>NHibernate.Driver.SqlServerCeDriver<span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">property<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n    <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">property<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"connection.connection_string\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>Data Source=FirstSample.sdf<span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">property<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n\r\n    <span style=\"color: #0000ff;\">&lt;<\/span><span style=\"color: #800000;\">property<\/span> <span style=\"color: #ff0000;\">name<\/span><span style=\"color: #0000ff;\">=\"show_sql\"<\/span><span style=\"color: #0000ff;\">&gt;<\/span>true<span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">property<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n  <span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">session-factory<\/span><span style=\"color: #0000ff;\">&gt;<\/span>\r\n<span style=\"color: #0000ff;\">&lt;\/<\/span><span style=\"color: #800000;\">hibernate-configuration<\/span><span style=\"color: #0000ff;\">&gt;<\/span><\/pre>\n<p style=\"text-align: justify;\">Con este fichero de configuraci\u00f3n de indicamos a NH que queremos usar MS SQL Compact Edition como nuestra base de datos destino. El nombre de la base de datos ser\u00e1 FirstSample.sdf. Hemos tambi\u00e9n definido que queremos ver el SQL generado y enviado a la base por NH (es muy recomendable para\u00a0prop\u00f3sitos\u00a0de depuraci\u00f3n durante el desarrollo).<\/p>\n<p style=\"text-align: justify;\">A\u00f1adimos una base de datos vacia llamada FirstSample.sdf al proyecto. Es necesario seleccionar local database (base de datos local como plantilla o template).<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/AddNewItem.png\" \/><\/p>\n<p style=\"text-align: justify;\">Pulsamos en add o a\u00f1adir e ignoramos el asistente o wizard para la creaci\u00f3n de un Dataset, presionando cancelar.<\/p>\n<p style=\"text-align: justify;\"><strong>Testeando la configuraci\u00f3n o setup establecido<\/strong><\/p>\n<p style=\"text-align: justify;\">Es el momento de testear nuestra configuraci\u00f3n. Lo primero es verifica que tenemos los siguientes ficheros \u00a0en la carpeta Sharedlibs.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/SharedLibs.png\" \/><\/p>\n<p style=\"text-align: justify;\">Los \u00faltimos 8 ficheros pueden encontrarse en el directorio de la carpeta de programa \u00a0&#8220;Microsoft SQL Server Compact Edition&#8221;<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/sqlce.png\" \/><\/p>\n<p style=\"text-align: justify;\">Observaci\u00f3n: El\u00a0<b>System.Data.SqlServerCe.dll <\/b>se encuentra localizado en la subcarpeta Desktop.<\/p>\n<p style=\"text-align: justify;\">El resto de fichero pueden encontrarse en la carpeta NHibernate.<\/p>\n<p style=\"text-align: justify;\">A\u00f1ade una referencia al ejemplo de tu proyecto. Adicionalmente a\u00f1ade referencias a NHhibernate.dll, nunit.framework y Systm.Data.SqlServerCe.dll (recuerda referenciar los ficheros situados en la carpeta SharedLibs).<\/p>\n<p style=\"text-align: justify;\">Presta atenci\u00f3n estableciendo la propiedad &#8220;Copia Local&#8221; a true para el ensamblado System.Data.SqlServerCE.dll porque por defecto es false. A\u00f1ade una copia de hibernate.cfg.xml al\u00a0ra\u00edz\u00a0de este proyecto.<\/p>\n<p style=\"text-align: justify;\">A\u00f1ade una clase llamada GenerateSchema_Fixture al proyecto. El proyecto deber\u00eda tener un aspecto como la imagen inferior.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/solutionex1.png\" \/><\/p>\n<p style=\"text-align: justify;\">Necesitaremos los 7 ficheros sqce*.dll en el directorio de salida. Podemos hacer esto usando un evento post-build en VS. Introduce el siguiente comando en el apartado Build Events-&gt;Post-build comand line: tal y como muestra la imagen inferior.<\/p>\n<p style=\"text-align: justify;\">copy $(ProjectDir)..\\..\\SharedLibs\\sqlce*.dll $(ProjectDir)$(OutDir)<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/AppProperties.png\" \/><\/p>\n<p style=\"text-align: justify;\">Ahora a\u00f1ade el siguiente c\u00f3digo al fichero GenerateSchema_Fixture<\/p>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">using<\/span> FirstSolution.Domain;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><span style=\"color: #0000ff;\">using<\/span> NHibernate.Cfg;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">using<\/span> NHibernate.Tool.hbm2ddl;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><span style=\"color: #0000ff;\">using<\/span> NUnit.Framework;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><span style=\"color: #0000ff;\">namespace<\/span> FirstSolution.Tests<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">{<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    [TestFixture]<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">    <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">class<\/span> GenerateSchema_Fixture<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        [Test]<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Can_generate_schema()<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            var cfg = <span style=\"color: #0000ff;\">new<\/span> Configuration();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            cfg.Configure();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            cfg.AddAssembly(<span style=\"color: #0000ff;\">typeof<\/span> (Product).Assembly);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            <span style=\"color: #0000ff;\">new<\/span> SchemaExport(cfg).Execute(<span style=\"color: #0000ff;\">false<\/span>, <span style=\"color: #0000ff;\">true<\/span>, <span style=\"color: #0000ff;\">false<\/span>, <span style=\"color: #0000ff;\">false<\/span>);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"font-family: Consolas, Monaco, monospace; font-size: 12px; line-height: 18px;\">}<\/span><\/pre>\n<p style=\"text-align: justify;\">La \u00a0primera l\u00ednea del m\u00e9todo test crea una nueva instancia de la clase configuraci\u00f3n NHibernate. Esta clase es usada para configurar NHibernate. En la segunda l\u00ednea le decimos a NH que se configure. NH revisar\u00e1 la informaci\u00f3n de configuraci\u00f3n hasta que nosotros no proporcionemos\u00a0alg\u00fan\u00a0valor en el\u00a0m\u00e9todo\u00a0test. Adem\u00e1s NH buscar\u00e1 un fichero llamado hibernate.cfg.xml en el directorio de salida. Esto es\u00a0exactamente\u00a0 lo que queremos\u00a0definiendo\u00a0nuestras opciones en este fichero.<\/p>\n<p style=\"text-align: justify;\">En la tercera l\u00ednea de c\u00f3digo le diremosa NH que puede encontrar informaci\u00f3n de mapeo en el ensamblado, el cual contiene tambien la clase producto. \u00a0Al tiempo que s\u00f3lo encontrar\u00e1 un fichero(product.hbm.xml) como un recurso embebido.<\/p>\n<p style=\"text-align: justify;\">La cuarta l\u00ednea de c\u00f3digo usa la clase SchemaExport de NH para generar autom\u00e1ticamente y de forma m\u00e1gica el schema en la base de datos por nosotros. SchemaExport crear\u00e1 la tabla de producto en la base y cada vez que la llamamos borrar\u00e1 la tabla, los datos y la recrear\u00e1.<\/p>\n<p style=\"text-align: justify;\">Nota: Con este m\u00e9todo test no queremos averiguar si NH hace el trabajo correctamente(puedes estar seguro que s\u00ed) pero si evaluar que hemos establecido nuestro sistema correctamente.. Sin embargo, puedes comprobar la base de datos y ver que la nueva tabla de productos se cre\u00f3.<\/p>\n<p style=\"text-align: justify;\">Si tenemos<a href=\"http:\/\/www.testdriven.net\/\" target=\"_blank\"> Testdriven.net<\/a> instalado podemos hacer clic con el bot\u00f3n derecho dentro del m\u00e9todo test y elegir &#8220;Run Test(s)&#8221; para ejecutar la prueba.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/RunTest.png\" \/><\/p>\n<p style=\"text-align: justify;\">Si todo es correcto, deberemos ver el siguiente resultado en la ventana de salida.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/TestResult.png\" \/><\/p>\n<p style=\"text-align: justify;\">Si tenemos instalado <a href=\"http:\/\/www.jetbrains.com\/resharper\/\" target=\"_blank\">ReSharper <\/a>\u00a0podemos empezar los test haciendo click en el circulo verde-amarillo en la parte izquierda y elegir run o ejecutar.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/RSTestinfo.png\" \/><\/p>\n<p style=\"text-align: justify;\">El resultado es como el siguiente.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/RSRunTest.png\" \/><\/p>\n<p style=\"text-align: justify;\"><em>En caso de problemas.<\/em><\/p>\n<p style=\"text-align: justify;\">Si las pruebas fallan, comprueba por segunda vez si tienes los siguientes ficheros en el directorio destino.<\/p>\n<p style=\"text-align: justify;\"><strong>Nuestras primeras operaciones CRUD<\/strong><\/p>\n<p style=\"text-align: justify;\">Continuamos con el taller pr\u00e1ctico. En la parte superior de esta entrada expongo que es un CRUD.<\/p>\n<p style=\"text-align: justify;\">Ahora\u00a0obviamente\u00a0 nuestro sistema esta listo para comenzar. Hemos implementado\u00a0satisfactoriamente\u00a0nuestro dominio, definido los ficheros de mapeo y configurado NHibernate. Finalmente hemos usado NH para generar\u00a0autom\u00e1ticamente\u00a0el schema de la base de datos desde nuestro dominio.<\/p>\n<p style=\"text-align: justify;\">Un nuevo concepto DDD (Domain Driven Design), o dise\u00f1o guiado por dominio es un enfoque para el desarrollo de software con necesidades complejas. No es una\u00a0tecnolog\u00eda\u00a0ni metodolog\u00eda. Las premisas del dise\u00f1o guiado por el dominio son las siguientes:<\/p>\n<p style=\"text-align: justify;\">&#8211; Poner como principal objetivo el proyecto y la l\u00f3gica del dominio.<br \/>\n&#8211; Basar los dise\u00f1os complejos en un modelo.<br \/>\n&#8211; Iniciar una creativa colaboraci\u00f3n entre t\u00e9cnicos y expertos del dominio para interactuar lo m\u00e1s cercano posible a los conceptos del problema.<br \/>\nEs pues un conjunto de practicas y terminolog\u00edas para tomar decisiones de dise\u00f1o que enfoquen y aceleren el manejo de dominios complejos en proyectos de software.<\/p>\n<p style=\"text-align: justify;\">Fue acu\u00f1ado por Eric Evans en su libro Domain-Driven Design. \u00a0Menciono el DDD, porque hemos definido un repositorio para todas las operaciones CRUD (crear, leer, actualizar y borrar), intentando satisfacer el\u00a0esp\u00edritu\u00a0 de DDD. Establecer las premisas futuras aunque la implementaci\u00f3n de la aplicaci\u00f3n no lo\u00a0despliegue.<\/p>\n<p style=\"text-align: justify;\">A\u00f1adimos una nueva interfaz para a la carpeta del dominio en nuestro proyecto. La llamaremos IProductRepository. Con el siguiente interfaz.<\/p>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">using<\/span> System;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><span style=\"color: #0000ff;\">using<\/span> System.Collections.Generic;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><span style=\"color: #0000ff;\">namespace<\/span> FirstSolution.Domain<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">{<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">interface<\/span> IProductRepository<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">    {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">void<\/span> Add(Product product);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        <span style=\"color: #0000ff;\">void<\/span> Update(Product product);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">void<\/span> Remove(Product product);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        Product GetById(Guid productId);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        Product GetByName(<span style=\"color: #0000ff;\">string<\/span> name);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        ICollection&lt;Product&gt; GetByCategory(<span style=\"color: #0000ff;\">string<\/span> category);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">}<\/pre>\n<p style=\"text-align: justify;\">Se a\u00f1ade una clase ProductRepository_Fixture para testear el proyecto y se a\u00f1ade el siguiente c\u00f3digo.<\/p>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">[TestFixture]<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">class<\/span> ProductRepository_Fixture<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">    {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">private<\/span> ISessionFactory _sessionFactory;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        <span style=\"color: #0000ff;\">private<\/span> Configuration _configuration;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        [TestFixtureSetUp]<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> TestFixtureSetUp()<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            _configuration = <span style=\"color: #0000ff;\">new<\/span> Configuration();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            _configuration.Configure();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            _configuration.AddAssembly(<span style=\"color: #0000ff;\">typeof<\/span> (Product).Assembly);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            _sessionFactory = _configuration.BuildSessionFactory();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">    }<\/pre>\n<p style=\"text-align: justify;\">En la cuarta l\u00ednea del m\u00e9todo TestFixtureSetUp creamos una sesion. Esto es un proceso costoso que\u00a0deber\u00eda\u00a0ser ejecutado solo una vez. Esta es la raz\u00f3n del por qu\u00e9 se pone dentro de este m\u00e9todo el cual es solo ejecutado una sola vez durante el ciclo de test.<\/p>\n<p style=\"text-align: justify;\">Para conservar nuestro\u00a0m\u00e9todos\u00a0de test sin efectos recreamos nuestro schema antes de la ejecuci\u00f3n de cada test. As\u00ed pues, a\u00f1adimos el siguiente m\u00e9todo<\/p>\n<pre style=\"text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 700px; color: black; line-height: 12pt; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4;\">[SetUp]\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> SetupContext()\r\n        {\r\n            <span style=\"color: #0000ff;\">new<\/span> SchemaExport(_configuration).Execute(<span style=\"color: #0000ff;\">false<\/span>, <span style=\"color: #0000ff;\">true<\/span>, <span style=\"color: #0000ff;\">false<\/span>, <span style=\"color: #0000ff;\">false<\/span>);\r\n        }<\/pre>\n<p style=\"text-align: justify;\">Y ahora podemos implementar el m\u00e9todo test y a\u00f1adir un nueva\u00a0instancia\u00a0de producto a la base de datos. Comenzar a\u00f1adiendo una nueva carpeta llamada Repositories a nuestro proyecto. A\u00f1adir una clase ProductRepository a esta carpeta. Hacer que ProductRepository herede de la interfaz IProductRepository.<\/p>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">using<\/span> System;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><span style=\"color: #0000ff;\">using<\/span> System.Collections.Generic;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">using<\/span> FirstSolution.Domain;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">namespace<\/span> FirstSolution.Repositories<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">{<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">    <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">class<\/span> ProductRepository : IProductRepository<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Add(Product product)<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            <span style=\"color: #0000ff;\">throw<\/span> <span style=\"color: #0000ff;\">new<\/span> NotImplementedException();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Update(Product product)<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            <span style=\"color: #0000ff;\">throw<\/span> <span style=\"color: #0000ff;\">new<\/span> NotImplementedException();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Remove(Product product)<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            <span style=\"color: #0000ff;\">throw<\/span> <span style=\"color: #0000ff;\">new<\/span> NotImplementedException();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">public<\/span> Product GetById(Guid productId)<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            <span style=\"color: #0000ff;\">throw<\/span> <span style=\"color: #0000ff;\">new<\/span> NotImplementedException();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        <span style=\"color: #0000ff;\">public<\/span> Product GetByName(<span style=\"color: #0000ff;\">string<\/span> name)<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            <span style=\"color: #0000ff;\">throw<\/span> <span style=\"color: #0000ff;\">new<\/span> NotImplementedException();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">public<\/span> ICollection&lt;Product&gt; GetByCategory(<span style=\"color: #0000ff;\">string<\/span> category)<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            <span style=\"color: #0000ff;\">throw<\/span> <span style=\"color: #0000ff;\">new<\/span> NotImplementedException();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">}<\/pre>\n<p style=\"text-align: justify;\">Manipulando datos.<\/p>\n<p style=\"text-align: justify;\">Ahora volcemos a la clase test \u00a0ProductRepository_Fixture e implementamos el primer m\u00e9todo test.<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\"> [Test]\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Can_add_new_product()\r\n        {\r\n            var product = <span style=\"color: #0000ff;\">new<\/span> Product {Name = <span style=\"color: #006080;\">\"Apple\"<\/span>, Category = <span style=\"color: #006080;\">\"Fruits\"<\/span>};\r\n            IProductRepository repository = <span style=\"color: #0000ff;\">new<\/span> ProductRepository();\r\n            repository.Add(product);\r\n        }<\/pre>\n<p style=\"text-align: justify;\">La primera ejecuci\u00f3n de este m\u00e9todo test fallar\u00e1 hasta que no implementemos el m\u00e9todo Add en la clase del repositorio. Vamos a realizarlo.Pero tendremos que esperar, hemos definido un peque\u00f1a clase de ayuda primero la cual nos proporciona objetos de session a demanda.<\/p>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">using<\/span> FirstSolution.Domain;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><span style=\"color: #0000ff;\">using<\/span> NHibernate;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">using<\/span> NHibernate.Cfg;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">namespace<\/span> FirstSolution.Repositories<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">{<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">    <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">class<\/span> NHibernateHelper<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        <span style=\"color: #0000ff;\">private<\/span> <span style=\"color: #0000ff;\">static<\/span> ISessionFactory _sessionFactory;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        <span style=\"color: #0000ff;\">private<\/span> <span style=\"color: #0000ff;\">static<\/span> ISessionFactory SessionFactory<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            get<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                <span style=\"color: #0000ff;\">if<\/span>(_sessionFactory == <span style=\"color: #0000ff;\">null<\/span>)<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                    var configuration = <span style=\"color: #0000ff;\">new<\/span> Configuration();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                    configuration.Configure();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                    configuration.AddAssembly(<span style=\"color: #0000ff;\">typeof<\/span>(Product).Assembly);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                    _sessionFactory = configuration.BuildSessionFactory();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                <span style=\"color: #0000ff;\">return<\/span> _sessionFactory;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">static<\/span> ISession OpenSession()<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            <span style=\"color: #0000ff;\">return<\/span> SessionFactory.OpenSession();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">    }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">}<\/pre>\n<p style=\"text-align: justify;\">Esta clase crea una f\u00e1brica de sesiones solo la primera vez que un cliente necesite una\u00a0sesi\u00f3n\u00a0 Ahora hemos definido el m\u00e9todo a\u00f1adir en el ProductRepository de la siguiente forma:<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\"> <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Add(Product product)\r\n        {\r\n            <span style=\"color: #0000ff;\">using<\/span> (ISession session = NHibernateHelper.OpenSession())\r\n                <span style=\"color: #0000ff;\">using<\/span> (ITransaction transaction = session.BeginTransaction())\r\n                {\r\n                    session.Save(product);\r\n                    transaction.Commit();\r\n                }\r\n        }<\/pre>\n<p style=\"text-align: justify;\">La segunda ejecuci\u00f3n del m\u00e9todo test fallar\u00e1 de nuevo desplegando el siguiente mensaje.<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/ShouldBeVirtual.png\" \/><\/p>\n<p style=\"text-align: justify;\">Esto es debido a que NHibernate se encuentra configurado por defecto para usar una carga perezosa (Lazy load) para todas las entidades. \u00a0Este es el enfoque recomendado para una m\u00e1xima flexibilidad.<\/p>\n<p style=\"text-align: justify;\">\u00bfC\u00f3mo podemos resolver este aspecto? Es f\u00e1cil, tenemos que \u00a0hacer todas las propiedades y m\u00e9todos <strong>virtuales<\/strong> de los objetos del dominio. De tal forma que la clase producto quedar\u00eda:<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\">    <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">class<\/span> Product\r\n    {\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">virtual<\/span> Guid Id { get; set; }\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">virtual<\/span> <span style=\"color: #0000ff;\">string<\/span> Name { get; set; }\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">virtual<\/span> <span style=\"color: #0000ff;\">string<\/span> Category { get; set; }\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">virtual<\/span> <span style=\"color: #0000ff;\">bool<\/span> Discontinued { get; set; }\r\n    }<\/pre>\n<p style=\"text-align: justify;\">Ahora ejecutemos el test de nuevo. Deber\u00eda ser correcto y mostrar la siguiente salida:<\/p>\n<p style=\"text-align: justify;\"><img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/TestOutput.png\" \/><\/p>\n<p style=\"text-align: justify;\">Observa el SQL arrojado por NHibernate.<\/p>\n<p style=\"text-align: justify;\">Ahora pensamos que hemos insertado correctamente el nuevo producto en la base de datos. Vamos a probar si realmente es as\u00ed.<\/p>\n<p style=\"text-align: justify;\">Vamos a extender nuestro m\u00e9todo test.<\/p>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">      [Test]<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Can_add_new_product()<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            var product = <span style=\"color: #0000ff;\">new<\/span> Product {Name = <span style=\"color: #006080;\">\"Apple\"<\/span>, Category = <span style=\"color: #006080;\">\"Fruits\"<\/span>};<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            IProductRepository repository = <span style=\"color: #0000ff;\">new<\/span> ProductRepository();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            repository.Add(product);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            <span style=\"color: #008000;\">\/\/ use session to try to load the product<\/span><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            <span style=\"color: #0000ff;\">using<\/span>(ISession session = _sessionFactory.OpenSession())<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                var fromDb = session.Get&lt;Product&gt;(product.Id);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                <span style=\"color: #008000;\">\/\/ Test that the product was successfully inserted<\/span><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                Assert.IsNotNull(fromDb);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                Assert.AreNotSame(product, fromDb);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                Assert.AreEqual(product.Name, fromDb.Name);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                Assert.AreEqual(product.Category, fromDb.Category);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        }<\/pre>\n<p style=\"text-align: justify;\">Ejecutemos el test de nuevo, esperemos que tenga \u00e9xito &#8230;<\/p>\n<p style=\"text-align: justify;\">Ahora nosotros hemos implementado tambi\u00e9n otros m\u00e9todos en el repositorio. Para probar esto, preferir\u00eda tener\u00a0un repositorio (que es la tabla de base de datos) que ya contiene algunos productos. Nada m\u00e1s f\u00e1cil que esto. S\u00f3lo tienemos que a\u00f1adir un CreateInitialData m\u00e9todo a la clase de prueba de la siguiente manera:<\/p>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><span style=\"color: #0000ff;\">private<\/span> <span style=\"color: #0000ff;\">readonly<\/span> Product[] _products = <span style=\"color: #0000ff;\">new<\/span>[]<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                 {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                     <span style=\"color: #0000ff;\">new<\/span> Product {Name = <span style=\"color: #006080;\">\"Melon\"<\/span>, Category = <span style=\"color: #006080;\">\"Fruits\"<\/span>},<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                     <span style=\"color: #0000ff;\">new<\/span> Product {Name = <span style=\"color: #006080;\">\"Pear\"<\/span>, Category = <span style=\"color: #006080;\">\"Fruits\"<\/span>},<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                     <span style=\"color: #0000ff;\">new<\/span> Product {Name = <span style=\"color: #006080;\">\"Milk\"<\/span>, Category = <span style=\"color: #006080;\">\"Beverages\"<\/span>},<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                     <span style=\"color: #0000ff;\">new<\/span> Product {Name = <span style=\"color: #006080;\">\"Coca Cola\"<\/span>, Category = <span style=\"color: #006080;\">\"Beverages\"<\/span>},<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                     <span style=\"color: #0000ff;\">new<\/span> Product {Name = <span style=\"color: #006080;\">\"Pepsi Cola\"<\/span>, Category = <span style=\"color: #006080;\">\"Beverages\"<\/span>},<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                 };<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">private<\/span> <span style=\"color: #0000ff;\">void<\/span> CreateInitialData()<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            <span style=\"color: #0000ff;\">using<\/span>(ISession session = _sessionFactory.OpenSession())<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                <span style=\"color: #0000ff;\">using<\/span>(ITransaction transaction = session.BeginTransaction())<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                    <span style=\"color: #0000ff;\">foreach<\/span> (var product <span style=\"color: #0000ff;\">in<\/span> _products)<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                        session.Save(product);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                    transaction.Commit();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        }<\/pre>\n<p style=\"text-align: justify;\">Llamar a este m\u00e9todo desde el m\u00e9todo SetupContext (despues de crear la llamada al esquema) y listo.\u00a0Ahora, cada vez que el esquema de base de datos se crea, \u00a0la base de datos se rellena con algunos productos.<\/p>\n<p style=\"text-align: justify;\">Vamos a probar el m\u00e9todo de actualizaci\u00f3n del repositorio con el siguiente c\u00f3digo:<\/p>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">    [Test]<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Can_update_existing_product()<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            var product = _products[0];<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            product.Name = <span style=\"color: #006080;\">\"Yellow Pear\"<\/span>;<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            IProductRepository repository = <span style=\"color: #0000ff;\">new<\/span> ProductRepository();<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            repository.Update(product);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\"><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            <span style=\"color: #008000;\">\/\/ use session to try to load the product<\/span><\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            <span style=\"color: #0000ff;\">using<\/span> (ISession session = _sessionFactory.OpenSession())<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">            {<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">                var fromDb = session.Get&lt;Product&gt;(product.Id);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">                Assert.AreEqual(product.Name, fromDb.Name);<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace;\">            }<\/pre>\n<pre style=\"color: black; font-size: 8pt; line-height: 12pt; text-align: start; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; font-family: consolas, 'Courier New', courier, monospace; background-color: white;\">        }<\/pre>\n<p style=\"text-align: justify;\">Cuando ejecutamos por primera vez este c\u00f3digo, fallar\u00e1 hasta que el m\u00e9todo Update no este implementado in el repositorio.<\/p>\n<p style=\"text-align: justify;\">Nota: Este es el comportamiento esperado ya que en TDD o desarrollo guiado en pruebas la primera vez que se ejecuta debe fallar.<\/p>\n<p style=\"text-align: justify;\">De forma an\u00e1loga al m\u00e9todo Add implementamos el m\u00e9todo Update del repositorio. La \u00fanica diferencia es que nosotros llamamos al m\u00e9todo de actualizaci\u00f3n del objeto de session de NHibernate en lugar \u00a0del m\u00e9todo de guardado.<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\">        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Update(Product product)\r\n        {\r\n            <span style=\"color: #0000ff;\">using<\/span> (ISession session = NHibernateHelper.OpenSession())\r\n            <span style=\"color: #0000ff;\">using<\/span> (ITransaction transaction = session.BeginTransaction())\r\n            {\r\n                session.Update(product);\r\n                transaction.Commit();\r\n            }\r\n        }<\/pre>\n<p style=\"text-align: justify;\">Ejecutamos el test de nuevo y vemos que tiene \u00e9xito.<\/p>\n<p style=\"text-align: justify;\">\u00a0<img decoding=\"async\" alt=\"\" src=\"http:\/\/nhforge.org\/cfs-file.ashx\/__key\/CommunityServer.Wikis.Components.Files\/howtonh\/TestSucceed.png\" \/><\/p>\n<p style=\"text-align: justify;\">El m\u00e9todo de borrado es directo. Cuando se prueba si el registro ha sido realmente eliminado, nos aseguramos que el valor devuelto de la sesi\u00f3n por el m\u00e9todo get es igual a null. Aqu\u00ed se encuentra el m\u00e9todo de test:<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\"> [Test]\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Can_remove_existing_product()\r\n        {\r\n            var product = _products[0];\r\n            IProductRepository repository = <span style=\"color: #0000ff;\">new<\/span> ProductRepository();\r\n            repository.Remove(product);\r\n\r\n            <span style=\"color: #0000ff;\">using<\/span> (ISession session = _sessionFactory.OpenSession())\r\n            {\r\n                var fromDb = session.Get&lt;Product&gt;(product.Id);\r\n                Assert.IsNull(fromDb);\r\n            }\r\n        }<\/pre>\n<p style=\"text-align: justify;\">y esto es la implementaci\u00f3n para eliminarlo del repositorio<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\">     <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Remove(Product product)\r\n        {\r\n            <span style=\"color: #0000ff;\">using<\/span> (ISession session = NHibernateHelper.OpenSession())\r\n                <span style=\"color: #0000ff;\">using<\/span> (ITransaction transaction = session.BeginTransaction())\r\n                {\r\n                    session.Delete(product);\r\n                    transaction.Commit();\r\n                }\r\n        }<\/pre>\n<p style=\"text-align: justify;\"><strong>Consultando la base de datos<\/strong><\/p>\n<p style=\"text-align: justify;\">Todav\u00eda nos queda implementar 3 m\u00e9todos que consultan a la base \u00a0de datos para los objetos. Vamos a empezar con lo m\u00e1s f\u00e1cil, GetByID, primero escribiremos la prueba.<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\">        [Test]\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Can_get_existing_product_by_id()\r\n        {\r\n            IProductRepository repository = <span style=\"color: #0000ff;\">new<\/span> ProductRepository();\r\n            var fromDb = repository.GetById(_products[1].Id);\r\n            Assert.IsNotNull(fromDb);\r\n            Assert.AreNotSame(_products[1], fromDb);\r\n            Assert.AreEqual(_products[1].Name, fromDb.Name);\r\n        }<\/pre>\n<p style=\"text-align: justify;\">Y el c\u00f3digo para completar el test<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\">       <span style=\"color: #0000ff;\">public<\/span> Product GetById(Guid productId)\r\n        {\r\n            <span style=\"color: #0000ff;\">using<\/span> (ISession session = NHibernateHelper.OpenSession())\r\n                <span style=\"color: #0000ff;\">return<\/span> session.Get&lt;Product&gt;(productId);\r\n        }<\/pre>\n<p style=\"text-align: justify;\">Ahora, eso fue f\u00e1cil. Para los siguientes dos m\u00e9todos usaremos un nuevo m\u00e9todo de el objeto session. Vamos a empezar con el m\u00e9todo GetByName. Como de costumbre, escribiremos la primera prueba, TDD<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\">       [Test]\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Can_get_existing_product_by_name()\r\n        {\r\n            IProductRepository repository = <span style=\"color: #0000ff;\">new<\/span> ProductRepository();\r\n            var fromDb = repository.GetByName(_products[1].Name);\r\n\r\n            Assert.IsNotNull(fromDb);\r\n            Assert.AreNotSame(_products[1], fromDb);\r\n            Assert.AreEqual(_products[1].Id, fromDb.Id);\r\n        }<\/pre>\n<p style=\"text-align: justify;\">La implementaci\u00f3n del m\u00e9todo GetByName se puede hacer mediante el uso de dos enfoques diferentes. El primero es usar HQL (Hibernate Query Language) y el segundo un HCQ (Hibernate Query Criteria). Vamos a empezar con HQL. HQL es un lenguaje orientado a objetos de consulta similar (pero no igual a) SQL.<\/p>\n<p style=\"text-align: justify;\">Para ser a\u00f1adido: Implementaci\u00f3n de GetByName utilizando HQL. Implementar HCQ como se muestraa funciona como se espera y devuelve un producto entidad.<\/p>\n<p style=\"text-align: justify;\">En el ejemplo anterior he introducido una t\u00e9cnica muy utilizada cuando se utiliza NHibernate. Se llama interfaces fluidas o fluent interfaces. Como resultado, el c\u00f3digo es menos detallado y m\u00e1s f\u00e1cil de entender. Se puede ver que una consulta HQL es una cadena que se han incorporado (con nombre) par\u00e1metros. Los par\u00e1metros van precedidos por un &#8216;:&#8217;. NHibernate define muchos m\u00e9todos helper (como SetString utilizado en el ejemplo) para asignar valores de varios tipos para esos par\u00e1metros. Finalmente mediante el uso de NHibernate UniqueResult le digo que espero que s\u00f3lo un registro para volver. Si hay m\u00e1s de un registro devuelto por la consulta HQL entonces se produce una excepci\u00f3n. Existe m\u00e1s informaci\u00f3n sobre HQL en l\u00ednea e internet.<\/p>\n<p style=\"text-align: justify;\">La segunda versi\u00f3n utiliza una consulta de criterios para buscar el producto solicitado. Es necesario agregar una referencia a NHibernate.Criterion en su p\u00e1gina repositorio.<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\">     <span style=\"color: #0000ff;\">public<\/span> Product GetByName(<span style=\"color: #0000ff;\">string<\/span> name)\r\n        {\r\n            <span style=\"color: #0000ff;\">using<\/span> (ISession session = NHibernateHelper.OpenSession())\r\n            {\r\n                Product product = session\r\n                    .CreateCriteria(<span style=\"color: #0000ff;\">typeof<\/span>(Product))\r\n                    .Add(Restrictions.Eq(<span style=\"color: #006080;\">\"Name\"<\/span>, name))\r\n                    .UniqueResult&lt;Product&gt;();\r\n                <span style=\"color: #0000ff;\">return<\/span> product;\r\n            }\r\n        }<\/pre>\n<p style=\"text-align: justify;\">Muchos usuarios de NHibernate piensan que este enfoque es m\u00e1s orientado a objetos. Por otro lado una consulta compleja escrita con la sintaxis de criterios r\u00e1pidamente puede ser dif\u00edcil de entender.<\/p>\n<p style=\"text-align: justify;\">El \u00faltimo m\u00e9todo a aplicar es GetByCategory. Este m\u00e9todo devuelve una lista de productos. La prueba puede ser implementada de la siguiente forma:<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 665.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\">  [Test]\r\n        <span style=\"color: #0000ff;\">public<\/span> <span style=\"color: #0000ff;\">void<\/span> Can_get_existing_products_by_category()\r\n        {\r\n            IProductRepository repository = <span style=\"color: #0000ff;\">new<\/span> ProductRepository();\r\n            var fromDb = repository.GetByCategory(<span style=\"color: #006080;\">\"Fruits\"<\/span>);\r\n\r\n            Assert.AreEqual(2, fromDb.Count);\r\n            Assert.IsTrue(IsInCollection(_products[0], fromDb));\r\n            Assert.IsTrue(IsInCollection(_products[1], fromDb));\r\n        }\r\n\r\n        <span style=\"color: #0000ff;\">private<\/span> <span style=\"color: #0000ff;\">bool<\/span> IsInCollection(Product product, ICollection&lt;Product&gt; fromDb)\r\n        {\r\n            <span style=\"color: #0000ff;\">foreach<\/span> (var item <span style=\"color: #0000ff;\">in<\/span> fromDb)\r\n                <span style=\"color: #0000ff;\">if<\/span> (product.Id == item.Id)\r\n                    <span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #0000ff;\">true<\/span>;\r\n            <span style=\"color: #0000ff;\">return<\/span> <span style=\"color: #0000ff;\">false<\/span>;\r\n        }<\/pre>\n<p style=\"text-align: justify;\">Y el m\u00e9todo debiera contener el siguiente c\u00f3digo:<\/p>\n<pre style=\"font-size: 8pt; line-height: 12pt; text-align: start; background-color: #f4f4f4; border-style: none; margin: 0em; padding: 0px; overflow: visible; width: 682.5px; color: black; font-family: consolas, 'Courier New', courier, monospace;\">       <span style=\"color: #0000ff;\">public<\/span> ICollection&lt;Product&gt; GetByCategory(<span style=\"color: #0000ff;\">string<\/span> category)\r\n        {\r\n            <span style=\"color: #0000ff;\">using<\/span> (ISession session = NHibernateHelper.OpenSession())\r\n            {\r\n                var products = session\r\n                    .CreateCriteria(<span style=\"color: #0000ff;\">typeof<\/span>(Product))\r\n                    .Add(Restrictions.Eq(<span style=\"color: #006080;\">\"Category\"<\/span>, category))\r\n                    .List&lt;Product&gt;();\r\n                <span style=\"color: #0000ff;\">return<\/span> products;\r\n            }\r\n        }<\/pre>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify;\"><strong>Resumen\u00a0<\/strong><\/p>\n<p style=\"text-align: justify;\"><span style=\"text-align: justify;\">En \u00a0esta entrada se ha visto como implementar un ejemplo b\u00e1sico. Se ha definido\u00a0<\/span>el mapeo hacia la base de datos y c\u00f3mo configurar NHibernate para que sea capaz de almacenar el dominio de \u00a0objetos persistentes en la base de datos. Se ha mostrado como escribir y testear m\u00e9todos CRUD para los objetos del dominio. Hemos seleccionado una base de datos de ejemplo MS SQL Edicion Compact, pero como he\u00a0comentado\u00a0puede dar soporte a otras bases, para ello es necesario cambiar el fichero hibernate.cfg.xml<\/p>\n<p style=\"text-align: justify;\">En f\u00edn, espero que esto os sirva para\u00a0introduciros\u00a0en el mundo ORM y NHibernate. A mi me sirve de aprendizaje, conocimiento y repaso. Es realmente, una extensi\u00f3n personalizada en Castellano de la ayuda\u00a0oficial\u00a0inicial, considero que existe poca documentaci\u00f3n en este idioma sobre el tema.<\/p>\n<p style=\"text-align: justify;\">Salu2, ya\u00a0pod\u00e9is\u00a0Hibernar &#8230;<\/p>\n<p style=\"text-align: justify;\">Otro video:\u00a0<a href=\"http:\/\/www.youtube.com\/watch?v=tJ49yXWXwow\" target=\"_blank\">http:\/\/www.youtube.com\/watch?v=tJ49yXWXwow<\/a><\/p>\n<p style=\"text-align: justify;\">Esta\u00a0documentaci\u00f3n\u00a0corresponde con la oficial, he traducido y ampliado t\u00e9rminos al castellano-Espa\u00f1ol \u00a0de:<br \/>\nMi primera aplicaci\u00f3n HNhibertate , web oficial<br \/>\n<a href=\"http:\/\/nhforge.org\/wikis\/howtonh\/your-first-nhibernate-based-application.aspx\" target=\"_blank\">http:\/\/nhforge.org\/wikis\/howtonh\/your-first-nhibernate-based-application.aspx<\/a><\/p>\n<p style=\"text-align: justify;\">\n","protected":false},"excerpt":{"rendered":"<p>Un ORM es una t\u00e9cnica-software para convertir\u00a0datos orientados a objetos a una base de datos relacional, usando un motor de persistencia. Se crea una base de datos orientada a objetos\u00a0virtual\u00a0sobre una base de datos relacional. \u00a0Por lo tanto su principal ventaja es &#8220;olvidarse&#8221; de la tediosa labor e crear todas las sentencias SQL para obtener,actualizar, insertar o borrar datos (CRUD como veremos adelante) en la base, as\u00ed como soporte para la persistencia. Existen dos\u00a0alternativas entre otras &#8230; Hibernate es una herramienta ORM (Object-Relational Mapping) \u00f3 Mapeo Objeto Relacional para la plataforma JAVA. NHibernate es la\u00a0alternativa de software\u00a0libre disponible para .NET en C#, distribuido bajo los t\u00e9rmimos LGPL. Es una de las primeras aproximaciones para el mundo .NET de proyectos ORM, a la cual se ha unido Microsoft con LinqToSQL y Entity Framework. Vamos a tratar NHibernate.\u00a0Al emplearle para el acceso a datos, el desarrollador\u00a0garantiza\u00a0que su aplicaci\u00f3n es independiente en cuanto al motor de datos empleado en producci\u00f3n. \u00a0Soporta los SGBDR m\u00e1s empleados en el mercado como puede ser MYSQL, Postgre, Oracle, MSSQL, etc. S\u00f3lo es necesario cambiar una l\u00ednea en el fichero de configuraci\u00f3n para que podamos emplear una base de datos distinta. NHiberbate facilita el mapeo de atributos entre una base de datos relacional tradicional y el modelo de objetos de una aplicaci\u00f3n, mediante archivos declarativos (XML) que permiten establecer estas relaciones. Intenta solucionar el problema de la diferencia entre los 2 modelos usados hoy en d\u00eda para organizar y manipular datos:\u00a0El usado en la memoria del ordenador (orientaci\u00f3n a objetos) y el usado en los sistemas gestores bases de datos (modelo relacional). Para lograrlo permite al desarrollador especificar c\u00f3mo es su modelo de datos, qu\u00e9 relaciones existen y qu\u00e9 forma tienen. Con esta informaci\u00f3n NHibernate le permite a la aplicaci\u00f3n manipular los datos de la base operando sobre<\/p>\n<p><a href=\"https:\/\/www.palentino.es\/blog\/nhibernate-mi-primera-aplicacion-orm-caso-practico\/\">(M\u00e1s)\u2026<\/a><\/p>\n","protected":false},"author":1,"featured_media":3626,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[40,5],"tags":[59,357,356],"class_list":["post-3625","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-bases-de-datos","category-programacion","tag-bases-de-datos-2","tag-crud","tag-nhibernate"],"_links":{"self":[{"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/posts\/3625","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/comments?post=3625"}],"version-history":[{"count":45,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/posts\/3625\/revisions"}],"predecessor-version":[{"id":3671,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/posts\/3625\/revisions\/3671"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/media\/3626"}],"wp:attachment":[{"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/media?parent=3625"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/categories?post=3625"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.palentino.es\/blog\/wp-json\/wp\/v2\/tags?post=3625"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}