{"id":1804,"date":"2014-12-16T18:04:10","date_gmt":"2014-12-16T18:04:10","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=1804"},"modified":"2023-06-28T01:20:48","modified_gmt":"2023-06-28T08:20:48","slug":"tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/","title":{"rendered":"TapMap Parte I: Trabajando con un Repositorio de T con Couchbase Server 2.0 y la Librer\u00eda Cliente .NET"},"content":{"rendered":"<p>He estado pensando en crear una aplicaci\u00f3n de referencia para usar .NET y Couchbase Server.  Mientras viajaba a Londres para la conferencia Progressive NoSQL en <a href=\"https:\/\/skillsmatter.com\/event\/nosql\/progressive-nosql-tutorials\/\">Las competencias importan<\/a>Pas\u00e9 las horas de espera a que mi habitaci\u00f3n de hotel estuviera lista escribiendo algo de c\u00f3digo en un Startbucks para una aplicaci\u00f3n que llamo TapMap.<\/p>\n<p>La aplicaci\u00f3n es bastante sencilla: se trata de una imitaci\u00f3n de Twitter centrada en las cervezas.  La idea b\u00e1sica es que alguien en un bar informe de que ha encontrado (y probablemente bebido) una cerveza concreta en un lugar determinado.  Ese informe se llama \"grifo\".  La funci\u00f3n \"mapa\" muestra una serie de grifos en un mapa de Nokia, utilizando GeoCouch.  El valor es que los usuarios pueden aprender r\u00e1pidamente d\u00f3nde encontrar sus cervezas favoritas.<\/p>\n<p><img decoding=\"async\" style=\"width: 683px;height: 600px\" src=\"https:\/\/www.couchbase.com\/blog\/sites\/default\/files\/uploads\/all\/images\/tapmap_0.PNG\" alt=\"\" \/><\/p>\n<p>El c\u00f3digo es todav\u00eda muy alfa y mis habilidades HTML necesitan ser mejoradas.  Pero he implementado lo suficiente como para empezar una serie de posts sobre los patrones de c\u00f3digo y las soluciones expuestas por TapMap.  Este post ser\u00e1 la primera parte y describir\u00e1 como crear un simple Repositorio de T para Couchbase usando la librer\u00eda .NET Client.  Puedes obtener el c\u00f3digo en <a href=\"https:\/\/github.com\/couchbaselabs\/TapMap\">https:\/\/github.com\/couchbaselabs\/TapMap<\/a>.<\/p>\n<p>Si no est\u00e1s familiarizado con los repositorios, la idea b\u00e1sica es que tienes una clase que es responsable del acceso a los datos de un objeto de dominio.  As\u00ed, para buscar un usuario por su direcci\u00f3n de correo electr\u00f3nico, utilizar\u00edas el m\u00e9todo GetByEmail(string email) del UserRepository.  Los repositorios tambi\u00e9n suelen contener m\u00e9todos CRUD est\u00e1ndar.  Hay un poco m\u00e1s en el patr\u00f3n, pero voy a demostrar su uso b\u00e1sico.  M\u00e1s informaci\u00f3n en <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ff649690.aspx\">https:\/\/msdn.microsoft.com\/en-us\/library\/ff649690.aspx<\/a>.<\/p>\n<p>La herencia es una forma natural de conseguir la reutilizaci\u00f3n del c\u00f3digo.  TapMap utiliza una clase base de repositorio para proporcionar m\u00e9todos CRUD a sus subclases.  Adem\u00e1s, la clase base hace uso de gen\u00e9ricos para que los m\u00e9todos CRUD puedan devolver instancias de T en lugar de s\u00f3lo objetos.  Restringir T a un tipo particular tambi\u00e9n permite algunos beneficios adicionales que discutir\u00e9 en breve.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> abstracto <span style=\"color: #6666cc;font-weight: bold\">clase<\/span> RepositoryBase<span style=\"color: #008000\">&lt;<\/span>T<span style=\"color: #008000\">&gt;<\/span> <span style=\"color: #0600ff;font-weight: bold\">donde<\/span> T <span style=\"color: #008000\">:<\/span> BaseModelo<br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #008080;font-style: italic\">\/\/m\u00e9todos basura aqu\u00ed<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>Como ya sabr\u00e1s, Couchbase Server 2.0 no impone un esquema a sus documentos.  Almacena un documento JSON con las propiedades que desees incluir.  Dicho esto, todos los documentos se almacenan con una propiedad reservada \"_id\" que deriva su valor de su clave.<\/p>\n<p>A\u00f1adir un documento de la siguiente manera:<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\">cliente<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Tienda<\/span><span style=\"color: #008000\">(<\/span>StoreMode<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">A\u00f1adir<\/span>, <span style=\"color: #666666\">\"cerveza_tres_fil\u00f3sofos\"<\/span>, <span style=\"color: #666666\">&#8220;{ <span style=\"color: #008080;font-weight: bold\">&#8220;<\/span>Nombre<span style=\"color: #008080;font-weight: bold\">&#8220;<\/span> : <span style=\"color: #008080;font-weight: bold\">&#8220;<\/span>Tres fil\u00f3sofos<span style=\"color: #008080;font-weight: bold\">&#8220;<\/span> }&#8221;<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><\/div>\n<\/div>\n<p>El resultado es un documento como el siguiente:<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #666666\">\"_id\"<\/span> <span style=\"color: #008000\">:<\/span> <span style=\"color: #666666\">\"cerveza_tres_fil\u00f3sofos\"<\/span>,<br \/>\n<span style=\"color: #666666\">\"nombre\"<\/span> <span style=\"color: #008000\">:<\/span> <span style=\"color: #666666\">\"Tres Fil\u00f3sofos\"<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>As\u00ed que para asegurarnos de que todos nuestros objetos modelo tienen esta propiedad ID crearemos una clase base modelo que defina una.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #008000\">[<\/span>Serializable<span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> abstracto <span style=\"color: #6666cc;font-weight: bold\">clase<\/span> BaseModelo<br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #008000\">[<\/span>JsonProperty<span style=\"color: #008000\">(<\/span>NombrePropiedad <span style=\"color: #008000\">=<\/span> <span style=\"color: #666666\">\"_id\"<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> Id <span style=\"color: #008000\">{<\/span> consiga<span style=\"color: #008000\">;<\/span> configure<span style=\"color: #008000\">;<\/span> <span style=\"color: #008000\">}<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>No voy a cavar en \u00e9l JsonProperty piezas aqu\u00ed.  Estoy usando Json.NET para la serializaci\u00f3n y escrib\u00ed m\u00e1s sobre ello en <a href=\"https:\/\/www.couchbase.com\/blog\/es\/develop\/net\/next\/\">https:\/\/www.couchbase.com\/develop\/net\/next<\/a>.  Lo importante a tener en cuenta es que tenemos objetos modelo con una propiedad \"Id\" y al restringir nuestros repositorios para utilizar subclases de ModelBase, sabemos que siempre tendremos esta propiedad.<\/p>\n<p>A la hora de crear vistas, es \u00fatil disponer de una taxonom\u00eda en los documentos para que sea f\u00e1cil encontrar todos los documentos \"cerveza\" o todos los documentos \"usuario\" o incluso encontrar un documento \"usuario\" con una direcci\u00f3n de correo electr\u00f3nico determinada.  Para facilitar este requisito, impondremos una propiedad \"tipo\" a todos los documentos del modelo.  A nuestra ModelBase, a\u00f1adiremos una propiedad Type abstracta y de s\u00f3lo lectura.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #008000\">[<\/span>JsonProperty<span style=\"color: #008000\">(<\/span><span style=\"color: #666666\">\"tipo\"<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> abstracto <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> Tipo <span style=\"color: #008000\">{<\/span> consiga<span style=\"color: #008000\">;<\/span> <span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>Ahora que entendemos las suposiciones que podemos hacer de nuestro modelo, volvamos a nuestra clase RespositoryBase.<\/p>\n<p>Lo primero que nuestra clase RepositoryBase necesita hacer es definir una instancia de CouchbaseCliet.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\">\n<p><span style=\"color: #0600ff;font-weight: bold\">protegido<\/span> <span style=\"color: #0600ff;font-weight: bold\">est\u00e1tico<\/span> <span style=\"color: #0600ff;font-weight: bold\">s\u00f3lo lectura<\/span> CouchbaseClient _Cliente <span style=\"color: #008000\">=<\/span> <span style=\"color: #0600ff;font-weight: bold\">null<\/span><span style=\"color: #008000\">;<\/span><\/p>\n<p><span style=\"color: #0600ff;font-weight: bold\">est\u00e1tico<\/span> RepositoryBase<span style=\"color: #008000\">(<\/span><span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\nCliente <span style=\"color: #008000\">=<\/span> <a href=\"https:\/\/www.google.com\/search?q=new+msdn.microsoft.com\"><span style=\"color: #008000\">nuevo<\/span><\/a> CouchbaseClient<span style=\"color: #008000\">(<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<\/div>\n<\/div>\n<p>Dado que la configuraci\u00f3n del cliente es costosa, vamos a asegurarnos de que s\u00f3lo ocurra una vez por AppDomain creando una instancia est\u00e1tica de s\u00f3lo lectura que se instancie en un constructor est\u00e1tico.  El cliente es expuesto como un campo protegido a subclases que necesitan extender los m\u00e9todos CRUD b\u00e1sicos en nuestra clase base.  N\u00f3tese que este cliente depende de que el Web.config haya definido la secci\u00f3n \"couchbase\".  En alg\u00fan momento, a\u00f1adir\u00e9 una versi\u00f3n IoC amigable de nuestro RepositoryBase.<\/p>\n<p>La base del repositorio define los m\u00e9todos Crear, Actualizar y Guardar.  Estos m\u00e9todos a su vez llaman al m\u00e9todo privado \"store\" con el valor apropiado de StoreMode.  Crear y Actualizar son sencillos.  Guardar simplemente crea un documento cuando la clave no existe y lo reemplaza cuando existe.  Los valores de retorno son el valor CAS de la operaci\u00f3n.  En alg\u00fan momento, a\u00f1adir\u00e9 CAS como par\u00e1metro opcional.  El m\u00e9todo store tambi\u00e9n llama a un m\u00e9todo de extensi\u00f3n CasJson que serializa todos los objetos a cadenas JSON antes de guardarlos en Couchbase.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\">\n<p><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #0600ff;font-weight: bold\">virtual<\/span> <span style=\"color: #6666cc;font-weight: bold\">ulong<\/span> Cree<span style=\"color: #008000\">(<\/span>Modelo T<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> tienda<span style=\"color: #008000\">(<\/span>StoreMode<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">A\u00f1adir<\/span>, modelo<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<p><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #0600ff;font-weight: bold\">virtual<\/span> <span style=\"color: #6666cc;font-weight: bold\">ulong<\/span> Actualizaci\u00f3n<span style=\"color: #008000\">(<\/span>Modelo T<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> tienda<span style=\"color: #008000\">(<\/span>StoreMode<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Sustituir<\/span>, modelo<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<p><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #0600ff;font-weight: bold\">virtual<\/span> <span style=\"color: #6666cc;font-weight: bold\">ulong<\/span> Guardar<span style=\"color: #008000\">(<\/span>Modelo T<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> tienda<span style=\"color: #008000\">(<\/span>StoreMode<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Establecer<\/span>, modelo<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<p><span style=\"color: #0600ff;font-weight: bold\">privado<\/span> <span style=\"color: #6666cc;font-weight: bold\">ulong<\/span> tienda<span style=\"color: #008000\">(<\/span>Modo StoreMode, modelo T<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\nvar resultado <span style=\"color: #008000\">=<\/span> Cliente<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">CasJson<\/span><span style=\"color: #008000\">(<\/span>modo, BuildKey<span style=\"color: #008000\">(<\/span>modelo<span style=\"color: #008000\">)<\/span>, modelo<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> resultado<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Resultado<\/span> <span style=\"color: #008000\">?<\/span> resultado<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Cas<\/span> <span style=\"color: #008000\">:<\/span> <span style=\"color: #ff0000\">0<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<\/div>\n<\/div>\n<p>El m\u00e9todo privado store tambi\u00e9n hace uso del m\u00e9todo protegido BuildKey para crear claves mediante una convenci\u00f3n.  Espec\u00edficamente, las claves se componen a partir de la propiedad Type del modelo y su propiedad Id, con espacios reemplazados por guiones bajos.  TapMap en realidad no hace uso de esta versi\u00f3n de BuildKey ya que se sobrescribe en las subclases que utilizan Create, Update o Save.  Estoy considerando a\u00f1adir una propiedad \"Name\" al ModelBase para permitir componer una clave basada en un tipo y un nombre.  Por ejemplo, una cerveza con nombre \"Old Yankee Ale\" obtiene una clave \"beer_Old_Yankee_Ale\".<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #0600ff;font-weight: bold\">protegido<\/span> <span style=\"color: #0600ff;font-weight: bold\">virtual<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> BuildKey<span style=\"color: #008000\">(<\/span>Modelo T<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Concat<\/span><span style=\"color: #008000\">(<\/span>modelo<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Tipo<\/span>, <span style=\"color: #666666\">&#8220;_&#8221;<\/span>, modelo<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Id<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Sustituir<\/span><span style=\"color: #008000\">(<\/span><span style=\"color: #666666\">&#8221; &#8220;<\/span>, <span style=\"color: #666666\">&#8220;_&#8221;<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>El m\u00e9todo Get toma el _id del documento como argumento cuando es llamado.  Ese valor se utiliza como clave para llamar al m\u00e9todo Get gen\u00e9rico del cliente.  Otro m\u00e9todo de extensi\u00f3n - GetJson(string id) - tambi\u00e9n est\u00e1 siendo utilizado por el m\u00e9todo Get para convertir el documento JSON en una instancia de T.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #0600ff;font-weight: bold\">virtual<\/span> T Obtener<span style=\"color: #008000\">(<\/span><span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> id<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\nvar doc <span style=\"color: #008000\">=<\/span> Cliente<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">GetJson<\/span><span style=\"color: #008000\">&lt;<\/span>T<span style=\"color: #008000\">&gt;<\/span><span style=\"color: #008000\">(<\/span>id<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">si<\/span> <span style=\"color: #008000\">(<\/span>doc <span style=\"color: #008000\">!=<\/span> <span style=\"color: #0600ff;font-weight: bold\">null<\/span><span style=\"color: #008000\">)<\/span> doc<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Id<\/span> <span style=\"color: #008000\">=<\/span> id<span style=\"color: #008000\">;<\/span> <span style=\"color: #008080;font-style: italic\">\/\/servidor no devuelve el _id en el JSON<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> doc<span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>Remove es muy sencillo.  Simplemente toma la clave del documento (de nuevo, tambi\u00e9n el _id) y elimina el elemento de Couchbase.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #0600ff;font-weight: bold\">virtual<\/span> <span style=\"color: #6666cc;font-weight: bold\">void<\/span> Eliminar<span style=\"color: #008000\">(<\/span><span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> id<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\nCliente<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Eliminar<\/span><span style=\"color: #008000\">(<\/span>id<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>Proporcionar soporte base para el acceso a las vistas se realiza por convenci\u00f3n en el m\u00e9todo View.  Este m\u00e9todo asume que el nombre del documento de dise\u00f1o es el nombre del tipo de modelo pluralizado.  As\u00ed BeerRepository tendr\u00e1 autom\u00e1ticamente sus peticiones de vista mapeadas a un documento de dise\u00f1o llamado \"cervezas\".  El m\u00e9todo View devuelve una instancia IView.  Dado que la llamada HTTP no se realiza hasta que un llamador itera sobre el IView, las subclases pueden llamar a la vista utilizando los m\u00e9todos de consulta fluidos.  Tendr\u00e9 un ejemplo de una llamada espec\u00edfica a la vista en breve.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #0600ff;font-weight: bold\">protegido<\/span> Ver<span style=\"color: #008000\">&lt;<\/span>IViewRow<span style=\"color: #008000\">&gt;<\/span> Ver<span style=\"color: #008000\">(<\/span><span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> viewName<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> Cliente<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">GetView<\/span><span style=\"color: #008000\">(<\/span>InflectorNet<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Pluralizar<\/span><span style=\"color: #008000\">(<\/span><a href=\"https:\/\/www.google.com\/search?q=typeof+msdn.microsoft.com\"><span style=\"color: #008000\">tipode<\/span><\/a><span style=\"color: #008000\">(<\/span>T<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Nombre<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">ToLower<\/span><span style=\"color: #008000\">(<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">)<\/span>, viewName<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>Tambi\u00e9n existe actualmente un m\u00e9todo SpatialView, que permite realizar consultas geoespaciales utilizando GeoCouch.  El m\u00e9todo GetSpatialView del cliente es actualmente experimental y no ha sido a\u00f1adido a la rama maestra 1.2 del cliente.  Sin embargo, se a\u00f1adir\u00e1 pr\u00f3ximamente.  Si clona el repositorio TapMap, obtendr\u00e1 un binario del cliente con soporte para este m\u00e9todo.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #0600ff;font-weight: bold\">protegido<\/span> Ver<span style=\"color: #008000\">&lt;<\/span>ISpatialViewRow<span style=\"color: #008000\">&gt;<\/span> SpatialView<span style=\"color: #008000\">(<\/span><span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> viewName<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> Cliente<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">GetSpatialView<\/span><span style=\"color: #008000\">(<\/span>InflectorNet<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Pluralizar<\/span><span style=\"color: #008000\">(<\/span><a href=\"https:\/\/www.google.com\/search?q=typeof+msdn.microsoft.com\"><span style=\"color: #008000\">tipode<\/span><\/a><span style=\"color: #008000\">(<\/span>T<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Nombre<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">ToLower<\/span><span style=\"color: #008000\">(<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">)<\/span>, viewName<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>Eso cubre RepositoryBase.  As\u00ed que ahora que hemos visto sus m\u00e9todos y su prop\u00f3sito, vamos a profundizar en una subclase.  Primero, la clase modelo User define propiedades para Username, Email y Password.  Tambi\u00e9n proporciona mapeos de propiedades JSON a versiones en min\u00fasculas de las propiedades de la clase.  Observa tambi\u00e9n que User extiende ModelBase e implementa la propiedad Type devolviendo la cadena \"user\".<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\">\n<p><span style=\"color: #008000\">[<\/span>Serializable<span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #6666cc;font-weight: bold\">clase<\/span> Usuario <span style=\"color: #008000\">:<\/span> BaseModelo<br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #008000\">[<\/span>Requerido<span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #008000\">[<\/span>JsonProperty<span style=\"color: #008000\">(<\/span><span style=\"color: #666666\">\"nombre de usuario\"<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> Nombre de usuario <span style=\"color: #008000\">{<\/span> consiga<span style=\"color: #008000\">;<\/span> configure<span style=\"color: #008000\">;<\/span> <span style=\"color: #008000\">}<\/span><\/p>\n<p><span style=\"color: #008000\">[<\/span>Requerido<span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #008000\">[<\/span>JsonProperty<span style=\"color: #008000\">(<\/span><span style=\"color: #666666\">\"email\"<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> Correo electr\u00f3nico <span style=\"color: #008000\">{<\/span> consiga<span style=\"color: #008000\">;<\/span> configure<span style=\"color: #008000\">;<\/span> <span style=\"color: #008000\">}<\/span><\/p>\n<p><span style=\"color: #008000\">[<\/span>Requerido<span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #008000\">[<\/span>JsonProperty<span style=\"color: #008000\">(<\/span><span style=\"color: #666666\">\"contrase\u00f1a\"<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">]<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> Contrase\u00f1a <span style=\"color: #008000\">{<\/span> consiga<span style=\"color: #008000\">;<\/span> configure<span style=\"color: #008000\">;<\/span> <span style=\"color: #008000\">}<\/span><\/p>\n<p><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #0600ff;font-weight: bold\">anular<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> Tipo<br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\nconsiga <span style=\"color: #008000\">{<\/span> <span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> <span style=\"color: #666666\">\"usuario\"<\/span><span style=\"color: #008000\">;<\/span> <span style=\"color: #008000\">}<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<\/div>\n<\/div>\n<p>La clase UserRepository extiende RepositoryBase con T de tipo User.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #6666cc;font-weight: bold\">clase<\/span> UsuarioRepositorio <span style=\"color: #008000\">:<\/span> RepositoryBase<span style=\"color: #008000\">&lt;<\/span>Usuario<span style=\"color: #008000\">&gt;<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #008080;font-style: italic\">\/\/m\u00e9todos<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>Con la simple definici\u00f3n anterior, el UserRepository tiene bastante poder.  Puede realizar toda la funcionalidad CRUD b\u00e1sica definida en su clase base.  Sin embargo, hay algunos escenarios especiales para trabajar con documentos de Usuario en la aplicaci\u00f3n y el UserRepository a\u00f1ade m\u00e9todos para soportar estos escenarios.<\/p>\n<p>Cuando un usuario se registra con un nombre de usuario y una contrase\u00f1a, una opci\u00f3n ser\u00eda crear una vista que emita una clave compuesta de nombre de usuario y contrase\u00f1a.  Sin embargo, una alternativa mejor es utilizar el nombre de usuario y la contrase\u00f1a para componer una clave para el documento.  Dicha clave nos permitir\u00e1 recuperar f\u00e1cilmente un documento de usuario cuando \u00e9ste se conecte.  Este enfoque ahorra espacio al no tener que crear el \u00edndice secundario de la vista y permite una clave m\u00e1s r\u00e1pida al utilizar la b\u00fasqueda hashtable.<\/p>\n<p>En el m\u00e9todo anulado Create, el nombre de usuario (Id) y la contrase\u00f1a (hash) se utilizan para crear una clave de la forma user_Username_HashedPassword.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> <span style=\"color: #0600ff;font-weight: bold\">anular<\/span> <span style=\"color: #6666cc;font-weight: bold\">ulong<\/span> Cree<span style=\"color: #008000\">(<\/span>Modelo de usuario<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\nmodelo<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Contrase\u00f1a<\/span> <span style=\"color: #008000\">=<\/span> HashHelper<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">ToHashedString<\/span><span style=\"color: #008000\">(<\/span>modelo<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Contrase\u00f1a<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\nmodelo<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Id<\/span> <span style=\"color: #008000\">=<\/span> BuildKey<span style=\"color: #008000\">(<\/span>modelo<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\nvar resultado <span style=\"color: #008000\">=<\/span> Cliente<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">CasJson<\/span><span style=\"color: #008000\">(<\/span>StoreMode<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">A\u00f1adir<\/span>BuildKey<span style=\"color: #008000\">(<\/span>modelo<span style=\"color: #008000\">)<\/span>, modelo<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> resultado<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Resultado<\/span> <span style=\"color: #008000\">?<\/span> resultado<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Cas<\/span> <span style=\"color: #008000\">:<\/span> <span style=\"color: #ff0000\">0<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>BuildKey tambi\u00e9n est\u00e1 sobrecargado para permitir el nuevo formato de clave.   El m\u00e9todo privado buildKey es necesario para el m\u00e9todo Get sobrecargado que veremos en breve.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\">\n<p><span style=\"color: #0600ff;font-weight: bold\">protegido<\/span> <span style=\"color: #0600ff;font-weight: bold\">anular<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> BuildKey<span style=\"color: #008000\">(<\/span>Usuario<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> buildKey<span style=\"color: #008000\">(<\/span>usuario<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Nombre de usuario<\/span>usuario<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Contrase\u00f1a<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<p><span style=\"color: #0600ff;font-weight: bold\">privado<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> buildKey<span style=\"color: #008000\">(<\/span><span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> nombre de usuario, <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> contrase\u00f1a<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Concat<\/span><span style=\"color: #008000\">(<\/span><span style=\"color: #666666\">\"usuario_\"<\/span>nombre de usuario, <span style=\"color: #666666\">&#8220;_&#8221;<\/span>Contrase\u00f1a<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<\/div>\n<\/div>\n<p>El m\u00e9todo Get definido en RepositoryBase asume una b\u00fasqueda por clave.  En lugar de exponer el formato especial de la clave de usuario a la clase UserController que llama, Get est\u00e1 sobrecargado para aceptar un nombre de usuario y una contrase\u00f1a a partir de los cuales se compone la nueva clave.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\"><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> Obtener usuario<span style=\"color: #008000\">(<\/span><span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> nombre de usuario, <span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> contrase\u00f1a<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> Visite<span style=\"color: #008000\">(<\/span>buildKey<span style=\"color: #008000\">(<\/span>nombre de usuario, HashHelper<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">ToHashedString<\/span><span style=\"color: #008000\">(<\/span>contrase\u00f1a<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/div>\n<\/div>\n<p>La clase UserRepository tambi\u00e9n es responsable de ayudar a responder a las preguntas de si un nombre de usuario o un correo electr\u00f3nico son \u00fanicos.  Para ello, se utilizan dos vistas.  La primera simplemente emite el email como clave para todos los documentos de usuario; la segunda emite el nombre de usuario como clave.  Hay formas m\u00e1s ingeniosas de crear estos \u00edndices, pero para simplificar las cosas, hay un mapeo uno a uno entre la propiedad a comprobar y su vista.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\">\n<p>funci\u00f3n <span style=\"color: #008000\">(<\/span>doc<span style=\"color: #008000\">)<\/span> <span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">si<\/span> <span style=\"color: #008000\">(<\/span>doc<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">tipo<\/span> <span style=\"color: #008000\">==<\/span> <span style=\"color: #666666\">\"usuario\"<\/span><span style=\"color: #008000\">)<\/span> <span style=\"color: #008000\">{<\/span><br \/>\nemite<span style=\"color: #008000\">(<\/span>doc<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">correo electr\u00f3nico<\/span>, <span style=\"color: #0600ff;font-weight: bold\">null<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<p>funci\u00f3n <span style=\"color: #008000\">(<\/span>doc<span style=\"color: #008000\">)<\/span> <span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">si<\/span> <span style=\"color: #008000\">(<\/span>doc<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">tipo<\/span> <span style=\"color: #008000\">==<\/span> <span style=\"color: #666666\">\"usuario\"<\/span><span style=\"color: #008000\">)<\/span> <span style=\"color: #008000\">{<\/span><br \/>\nemite<span style=\"color: #008000\">(<\/span>doc<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">usrename<\/span>, <span style=\"color: #0600ff;font-weight: bold\">null<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<\/div>\n<\/div>\n<p>El UserRepository define los m\u00e9todos GetByEmail y GetByUsername, que utilizan el m\u00e9todo base View para consultar sus respectivas vistas.  En ambos m\u00e9todos, el l\u00edmite se establece en 1 y hay un retorno duro en la primera iteraci\u00f3n, ya que s\u00f3lo nos importa que exista un \u00fanico elemento con este valor de propiedad.  No se permiten vistas obsoletas, ya que estamos tratando de hacer cumplir la unicidad de los datos y tenemos que asegurarnos de que tenemos el \u00edndice de vista m\u00e1s actualizado posible.<\/p>\n<div class=\"geshifilter\">\n<div class=\"csharp geshifilter-csharp\" style=\"font-family: monospace\">\n<p><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> Usuario GetByEmail<span style=\"color: #008000\">(<\/span><span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> correo electr\u00f3nico<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">foreach<\/span> <span style=\"color: #008000\">(<\/span>var art\u00edculo <span style=\"color: #0600ff;font-weight: bold\">en<\/span> Ver<span style=\"color: #008000\">(<\/span><span style=\"color: #666666\">\"by_email\"<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">L\u00edmite<\/span><span style=\"color: #008000\">(<\/span><span style=\"color: #ff0000\">1<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Clave<\/span><span style=\"color: #008000\">(<\/span>correo electr\u00f3nico<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Rancio<\/span><span style=\"color: #008000\">(<\/span>StaleMode<span style=\"color: #008000\">.<\/span><span style=\"color: #0600ff;font-weight: bold\">Falso<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> Visite<span style=\"color: #008000\">(<\/span>art\u00edculo<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">ItemId<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> <span style=\"color: #0600ff;font-weight: bold\">null<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<p><span style=\"color: #0600ff;font-weight: bold\">p\u00fablico<\/span> Usuario GetByUsername<span style=\"color: #008000\">(<\/span><span style=\"color: #6666cc;font-weight: bold\">cadena<\/span> nombre de usuario<span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">foreach<\/span> <span style=\"color: #008000\">(<\/span>var art\u00edculo <span style=\"color: #0600ff;font-weight: bold\">en<\/span> Ver<span style=\"color: #008000\">(<\/span><span style=\"color: #666666\">\"por_nombre_de_usuario\"<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">L\u00edmite<\/span><span style=\"color: #008000\">(<\/span><span style=\"color: #ff0000\">1<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Clave<\/span><span style=\"color: #008000\">(<\/span>nombre de usuario<span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">Rancio<\/span><span style=\"color: #008000\">(<\/span>StaleMode<span style=\"color: #008000\">.<\/span><span style=\"color: #0600ff;font-weight: bold\">Falso<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">)<\/span><br \/>\n<span style=\"color: #008000\">{<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> Visite<span style=\"color: #008000\">(<\/span>art\u00edculo<span style=\"color: #008000\">.<\/span><span style=\"color: #0000ff\">ItemId<\/span><span style=\"color: #008000\">)<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><br \/>\n<span style=\"color: #0600ff;font-weight: bold\">devolver<\/span> <span style=\"color: #0600ff;font-weight: bold\">null<\/span><span style=\"color: #008000\">;<\/span><br \/>\n<span style=\"color: #008000\">}<\/span><\/p>\n<\/div>\n<\/div>\n<p>Explorar\u00e9 el UserController en otro momento para mostrar c\u00f3mo encaja todo.  Mi objetivo con este post era introducir el RepositoryBase y c\u00f3mo se extiende.<\/p>","protected":false},"excerpt":{"rendered":"<p>I\u2019ve been meaning to put together a reference application for using .NET and Couchbase Server.\u00a0 While traveling to London for the Progressive NoSQL conference at Skills Matter, I passed the hours waiting for my hotel room to be ready by [&hellip;]<\/p>","protected":false},"author":22,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[],"ppma_author":[8980],"class_list":["post-1804","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.5 (Yoast SEO v26.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Repository of T for Couchbase using the .NET Client Library<\/title>\n<meta name=\"description\" content=\"This post introduces to the RepositoryBase and how it\u2019s extended and how to create a simple Repository of T for Couchbase using the .NET Client Library.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"TapMap Part I: Working with a Repository of T with Couchbase Server 2.0 and the .NET Client Library\" \/>\n<meta property=\"og:description\" content=\"This post introduces to the RepositoryBase and how it\u2019s extended and how to create a simple Repository of T for Couchbase using the .NET Client Library.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-12-16T18:04:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-06-28T08:20:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/sites\/default\/files\/uploads\/all\/images\/tapmap_0.PNG\" \/>\n<meta name=\"author\" content=\"John Zablocki, NET. SDK Developer, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"John Zablocki, NET. SDK Developer, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/\"},\"author\":{\"name\":\"John Zablocki, NET. SDK Developer, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ee312fb775c13d20a32f1d455888a282\"},\"headline\":\"TapMap Part I: Working with a Repository of T with Couchbase Server 2.0 and the .NET Client Library\",\"datePublished\":\"2014-12-16T18:04:10+00:00\",\"dateModified\":\"2023-06-28T08:20:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/\"},\"wordCount\":1952,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/\",\"name\":\"Repository of T for Couchbase using the .NET Client Library\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2014-12-16T18:04:10+00:00\",\"dateModified\":\"2023-06-28T08:20:48+00:00\",\"description\":\"This post introduces to the RepositoryBase and how it\u2019s extended and how to create a simple Repository of T for Couchbase using the .NET Client Library.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"TapMap Part I: Working with a Repository of T with Couchbase Server 2.0 and the .NET Client Library\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ee312fb775c13d20a32f1d455888a282\",\"name\":\"John Zablocki, NET. SDK Developer, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/201925d9efc4992ce80385b76fdea34b\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8c5a77152c796c424a3f7f6d9fa31a999a7fe115d64c2acc93c4c0c014e6512a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8c5a77152c796c424a3f7f6d9fa31a999a7fe115d64c2acc93c4c0c014e6512a?s=96&d=mm&r=g\",\"caption\":\"John Zablocki, NET. SDK Developer, Couchbase\"},\"description\":\"John Zablocki is a NET. SDK Developer at Couchbase. John is also the organizer of Beantown ALT.NET and a former adjunct at Fairfield University. You can also check out the book on Amazon named \\\"Couchbase Essentials\\\" which explains how to install and configure Couchbase Server.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/john-zablocki\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Repository of T for Couchbase using the .NET Client Library","description":"Esta publicaci\u00f3n presenta RepositoryBase, c\u00f3mo se ampl\u00eda y c\u00f3mo crear un repositorio sencillo de T para Couchbase utilizando la biblioteca de clientes .NET.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/","og_locale":"es_MX","og_type":"article","og_title":"TapMap Part I: Working with a Repository of T with Couchbase Server 2.0 and the .NET Client Library","og_description":"This post introduces to the RepositoryBase and how it\u2019s extended and how to create a simple Repository of T for Couchbase using the .NET Client Library.","og_url":"https:\/\/www.couchbase.com\/blog\/es\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/","og_site_name":"The Couchbase Blog","article_published_time":"2014-12-16T18:04:10+00:00","article_modified_time":"2023-06-28T08:20:48+00:00","og_image":[{"url":"https:\/\/www.couchbase.com\/blog\/sites\/default\/files\/uploads\/all\/images\/tapmap_0.PNG","type":"","width":"","height":""}],"author":"John Zablocki, NET. SDK Developer, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"John Zablocki, NET. SDK Developer, Couchbase","Est. reading time":"9 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/"},"author":{"name":"John Zablocki, NET. SDK Developer, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ee312fb775c13d20a32f1d455888a282"},"headline":"TapMap Part I: Working with a Repository of T with Couchbase Server 2.0 and the .NET Client Library","datePublished":"2014-12-16T18:04:10+00:00","dateModified":"2023-06-28T08:20:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/"},"wordCount":1952,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Uncategorized"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/","url":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/","name":"Repository of T for Couchbase using the .NET Client Library","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2014-12-16T18:04:10+00:00","dateModified":"2023-06-28T08:20:48+00:00","description":"Esta publicaci\u00f3n presenta RepositoryBase, c\u00f3mo se ampl\u00eda y c\u00f3mo crear un repositorio sencillo de T para Couchbase utilizando la biblioteca de clientes .NET.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/tapmap-part-i-working-repository-t-couchbase-server-20-and-net-client-library\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"TapMap Part I: Working with a Repository of T with Couchbase Server 2.0 and the .NET Client Library"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/ee312fb775c13d20a32f1d455888a282","name":"John Zablocki, Desarrollador NET. Desarrollador SDK, Couchbase","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/201925d9efc4992ce80385b76fdea34b","url":"https:\/\/secure.gravatar.com\/avatar\/8c5a77152c796c424a3f7f6d9fa31a999a7fe115d64c2acc93c4c0c014e6512a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8c5a77152c796c424a3f7f6d9fa31a999a7fe115d64c2acc93c4c0c014e6512a?s=96&d=mm&r=g","caption":"John Zablocki, NET. SDK Developer, Couchbase"},"description":"John Zablocki is a NET. SDK Developer at Couchbase. John is also the organizer of Beantown ALT.NET and a former adjunct at Fairfield University. You can also check out the book on Amazon named \"Couchbase Essentials\" which explains how to install and configure Couchbase Server.","url":"https:\/\/www.couchbase.com\/blog\/es\/author\/john-zablocki\/"}]}},"authors":[{"term_id":8980,"user_id":22,"is_guest":0,"slug":"john-zablocki","display_name":"John Zablocki, NET. SDK Developer, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/8c5a77152c796c424a3f7f6d9fa31a999a7fe115d64c2acc93c4c0c014e6512a?s=96&d=mm&r=g","author_category":"","last_name":"Zablocki","first_name":"John","job_title":"","user_url":"","description":"John Zablocki es desarrollador de NET. SDK en Couchbase. John es tambi\u00e9n el organizador de Beantown ALT.NET y antiguo profesor adjunto en la Universidad de Fairfield.\r\nTambi\u00e9n puedes consultar el libro en Amazon llamado \"Couchbase Essentials\" que explica c\u00f3mo instalar y configurar Couchbase Server."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/1804","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/22"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=1804"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/1804\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=1804"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=1804"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=1804"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=1804"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}