- En la Parte 1 se explica cómo instalar y configurar Couchbase en Windows.
- En la Parte 2 se trató algo de la jerga de Couchbase que necesitarás conocer
- La parte 3 mostraba el ejemplo más simple de uso de Couchbase en ASP.NET
- En la Parte 4, hice algunas refacciones e introduje Linq2Couchbase
Esta es la última entrada del blog de esta serie que presenta Couchbase a desarrolladores ASP.NET (o viceversa, según se mire :). Completaré la aplicación de ejemplo que he estado creando con un conjunto completo de funciones CRUD. La aplicación ya muestra una lista de personas. Después de este post, serás capaz de añadir una nueva persona a través de la aplicación web (en lugar de directamente en la consola de Couchbase), editar una persona, y eliminar una persona.
Antes de empezar, un descargo de responsabilidad. He hecho algunos modelados decisiones en esta aplicación de ejemplo. He decidido que las claves de los documentos Persona deben tener el formato "Persona::{guid}", y he decidido que impondré el prefijo "Persona::" a nivel de repositorio. También he tomado la decisión de no utilizar ningún modelo de vista intermedio o modelos de edición en mi aplicación MVC, con el propósito de hacer una demostración concisa. De ninguna manera tienes que tomar las mismas decisiones que yo. Te animo a pensar en las implicaciones para tu caso de uso particular, y por favor, siéntete libre de discutir los méritos y compensaciones en los comentarios.
Añadir un nuevo documento de persona
En las entradas anteriores del blog, añadí nuevos documentos a través de la Consola de Couchbase. Ahora vamos a hacerlo posible a través de un formulario HTML estándar en una página ASP.NET.
En primer lugar, tengo que hacer un pequeño cambio en la clase Persona:
1 2 3 4 5 6 7 8 9 10 11 12 |
[Filtro de tipo de documento("Persona")] público clase Persona { público Persona() { Tipo = "Persona"; } [Clave] público cadena Id { consiga; configure; } público cadena Tipo { consiga; configure; } público cadena Nombre { consiga; configure; } público cadena Dirección { consiga; configure; } } |
He añadido un campo "Id" y lo he marcado con la etiqueta [Llave]
atributo. Este atributo viene de System.ComponentModel.DataAnnotations, pero Linq2Couchbase lo interpreta como "usa este campo para la clave de Couchbase".
Ahora, vamos a añadir una nueva acción muy simple a HomeController:
1 2 3 4 5 |
público AcciónResultado Añadir() { devolver Ver("Editar", nuevo Persona()); } |
Y enlazaré a eso con la navegación bootstrap (que colé previamente, y que de ninguna manera estás obligado a usar):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
@modelo CouchbaseAspNetEjemplo3.Modelos.Persona @{ <span clase="Apple-converted-space"> </span>ViewBag.Título = "Añadir : Ejemplo de Couchbase y ASP.NET"; } @utilizando (Html.BeginForm("Guardar", "Inicio", MétodoForm.Publicar en)) { <span clase="Apple-converted-space"> </span><p> <span clase="Apple-converted-space"> </span>@Html.EtiquetaPara(m => m.Nombre) <span clase="Apple-converted-space"> </span>@Html.TextBoxPara(m => m.Nombre) <span clase="Apple-converted-space"> </span></p> <span clase="Apple-converted-space"> </span><p> <span clase="Apple-converted-space"> </span>@Html.EtiquetaPara(m => m.Dirección) <span clase="Apple-converted-space"> </span>@Html.TextBoxPara(m => m.Dirección) <span clase="Apple-converted-space"> </span></p> <span clase="Apple-converted-space"> </span><entrada tipo="enviar" valor="Enviar" /> } |
Dado que ese formulario será POSTing a una acción Guardar, que necesita ser creado a continuación:
1 2 3 4 5 6 7 |
[HttpPost] público AcciónResultado Guardar(Persona modelo) { personaRepo.Guardar(modelo); devolver RedirectToAction("Índice"); } |
Observe que el tipo Persona utilizado en el parámetro es el mismo tipo que antes. Aquí es donde una aplicación web más compleja probablemente querría usar un modelo de edición, validación, mapeo, etcétera. Yo he omitido todo eso, y envío el modelo directamente a un nuevo método en PersonRepository:
1 2 3 4 5 6 7 8 9 10 |
público void Guardar(Persona persona) { // si no hay ID, asume que es una persona "nueva // y asignar un ID si (cadena.IsNullOrEmpty(persona.Id)) persona.Id = "Persona::" + Guía.NuevaGuid(); _contexto.Guardar(persona); } |
Este método de repositorio establecerá el ID, si no está ya establecido (lo estará, cuando cubramos 'Editar' más adelante). El método "Guardar" en IBucketContext es de Linq2Couchbase. Añadirá un nuevo documento si la clave no existe, o actualizará un documento existente si existe. Se conoce como una operación "upsert". De hecho, puedo hacer casi lo mismo sin Linq2Couchbase:
1 2 3 4 5 6 7 |
var doc = nuevo Documento { Id = "Persona::" + persona.Id, Contenido = persona }; _bucket.Upsert(doc); |
Editar un documento de persona existente
Ahora, quiero poder editar un documento de persona existente en mi sitio ASP.NET. En primer lugar, vamos a añadir un enlace de edición a cada persona, haciendo un cambio a _person.cshtml vista parcial.
1 2 3 |
@Modelo.Nombre @Html.ActionLink("[Editar]", "Editar", nuevo {id = Modelo.Id.Sustituir("Persona::", "")}) @Html.ActionLink("[Borrar]", "Borrar", nuevo {id = Modelo.Id.Sustituir("Persona::", "")}, nuevo { @clase="eliminarPersona"}) |
Una vez más, estoy usando bootstrap aquí, que no es necesario. También he añadido un enlace "eliminar" mientras estaba allí, que vamos a llegar a más adelante. Una cosa más que señalar: al crear los routeValues, he eliminado "Person::" del Id.. Si no hago esto, ASP.NET se quejará de una petición HTTP potencialmente maliciosa. Probablemente sería mejor dar a cada documento persona un más amigable "babosa" para usar en la URL, y tal vez usarla también como clave del documento. Eso va a depender de usted y su caso de uso.
Ahora necesito una acción Editar en HomeController:
1 2 3 4 5 6 |
público AcciónResultado Editar(Guía id) { var persona = personaRepo.GetPersonByKey(id); devolver Ver("Editar", persona); } |
Estoy reutilizando la misma vista Edit.cshtml, pero ahora necesito añadir un campo oculto para guardar el ID del documento.
1 2 |
<entrada <span clase="hljs-built_in">tipo</span>=<span clase="hljs-string">"oculto"</span> nombre=<span clase="hljs-string">"Id"</span> valor=<span clase="hljs-string">"@Modelo.Id"</span>/> |
¡Voilà! Ahora puedes añadir y editar documentos personales.
Esto puede no ser muy impresionante para aquellos que ya se sientan cómodos con ASP.NET MVC. Así que, a continuación, vamos a ver algo interesante que una base de datos NoSQL como Couchbase pone sobre la mesa.
Iteración de los datos almacenados en el documento de persona
Quiero recoger más información sobre una Persona. Digamos que quiero obtener un número de teléfono y una lista de las películas favoritas de esa persona. Con una base de datos relacional, eso significa que tendría que añadir como mínimo dos columnas y, más probablemente, al menos otra tabla que contenga las películas, con una clave externa.
Con Couchbase, no hay un esquema explícito. Así que en su lugar, todo lo que tengo que hacer es añadir un par de propiedades más a la clase Persona.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[Filtro de tipo de documento("Persona")] público clase Persona { público Persona() { Tipo = "Persona"; } [Clave] público cadena Id { consiga; configure; } público cadena Tipo { consiga; configure; } público cadena Nombre { consiga; configure; } público cadena Dirección { consiga; configure; } público cadena Número de teléfono { consiga; configure; } público Lista FavoriteMovies { consiga; configure; } } |
También tengo que añadir una interfaz de usuario correspondiente. He utilizado un poco de jQuery para permitir al usuario añadir cualquier número de películas. No voy a mostrar el código para ello aquí, porque los detalles de implementación no son importantes. Pero he hecho todo el muestra disponible en Githubpara que puedas comprobarlo más tarde si quieres.
También necesito hacer cambios en _person.cshtml para mostrar (condicionalmente) la información extra:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span clase="hljs-tag"><<span clase="hljs-title">div</span> <span clase="hljs-attributo">clase</span>=<span clase="hljs-value">"panel-cuerpo"</span>></span> @Modelo.Dirección @si (!cadena.IsNullOrEmpty(Modelo.Número de teléfono)) { <span clase="hljs-tag"><<span clase="hljs-title">br</span> /></span> @Modelo.Número de teléfono } @si (Modelo.FavoriteMovies != null && Modelo.FavoriteMovies.Cualquier()) { <span clase="hljs-tag"><<span clase="hljs-title">br</span>/></span> <span clase="hljs-tag"><<span clase="hljs-title">h4</span>></span>Favoritos Películas<span clase="hljs-tag"></<span clase="hljs-title">h4</span>></span> <span clase="hljs-tag"><<span clase="hljs-title">ul</span>></span> @foreach (var película en Modelo.FavoriteMovies) { <span clase="hljs-tag"><<span clase="hljs-title">li</span>></span>@película<span clase="hljs-tag"></<span clase="hljs-title">li</span>></span> } <span clase="hljs-tag"></<span clase="hljs-title">ul</span>></span> } <span clase="hljs-tag"></<span clase="hljs-title">div</span>></span> |
Y así es como se vería (esta vez con dos documentos Person):
No tuve que migrar un esquema SQL. No tuve que crear ningún tipo de relación de clave foránea. No tuve que configurar ningún mapeo OR/M. Simplemente añadí un par de campos nuevos, y Couchbase lo convirtió en un documento JSON correspondiente.
Suprimir un documento de persona
Ya he añadido el enlace "Eliminar", así que sólo tengo que crear una nueva acción de controlador...
1 2 3 4 5 6 |
público AcciónResultado Borrar(Guía id) { personaRepo.Borrar(id); devolver RedirectToAction("Índice"); } |
...y un nuevo método de repositorio:
1 2 3 4 5 |
público void Borrar(Guía id) { _bucket.Eliminar("Persona::" + id); } |
Observa que este método no está usando Linq2Couchbase. Está usando el método Remove de IBucket. Hay un Remove disponible en IBucketContext, pero necesitas pasarle un objeto, y no sólo una clave. Elegí usar el IBucket, pero no hay nada inherentemente superior en él.
Conclusión
Gracias por leer esta serie de blogs. Espero que estés en camino de considerar o incluso incluir Couchbase en tu próximo proyecto ASP.NET. Aquí tienes más enlaces interesantes para que continúes tu viaje con Couchbase:
- Quizá le interese la Proveedor de identidad ASP.NET para Couchbase (github). Si quieres almacenar información de identidad en Couchbase, esta es una forma de hacerlo. En el momento de publicar este blog, se trata de una versión preliminar para desarrolladores, y no es compatible con los inicios de sesión sociales.
- Linq2Couchbase es un gran proyecto con un montón de características y documentación, pero todavía es un trabajo en progreso. Si está interesado, le sugiero que visite Linq2Couchbase en Github. Haz preguntas en Gitter, y no dudes en enviar problemas o pull requests.
- Ahora mismo, Couchbase regala un premio de $500 para un uso creativo de Couchbase. ¿Iterar sobre este ejemplo ASP.NET? ¿Crear un plugin para tu IDE favorito? ¿Implementar esa funcionalidad que falta en el Proveedor de Identidad ASP.NET? Te llevarás un premio sólo por participar.
Conclusión
He puesto el código fuente completo de este ejemplo en Github.
¿Qué me he dejado? ¿Qué te impide probar Couchbase con ASP.NET hoy? Por favor, deja un comentario, ping me on Twittero envíame un correo electrónico (matthew.groves AT couchbase DOT com). Me encantaría saber de ti.