- 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 |
[DocumentTypeFilter("Person")] public class Person { public Person() { Type = "Person"; } [Key] public string Id { get; set; } public string Type { get; set; } public string Name { get; set; } public string Address { get; set; } } |
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 |
public ActionResult Add() { return View("Edit", new Person()); } |
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 |
@model CouchbaseAspNetExample3.Models.Person @{ <span class="Apple-converted-space"> </span>ViewBag.Title = "Add : Couchbase & ASP.NET Example"; } @using (Html.BeginForm("Save", "Home", FormMethod.Post)) { <span class="Apple-converted-space"> </span><p> <span class="Apple-converted-space"> </span>@Html.LabelFor(m => m.Name) <span class="Apple-converted-space"> </span>@Html.TextBoxFor(m => m.Name) <span class="Apple-converted-space"> </span></p> <span class="Apple-converted-space"> </span><p> <span class="Apple-converted-space"> </span>@Html.LabelFor(m => m.Address) <span class="Apple-converted-space"> </span>@Html.TextBoxFor(m => m.Address) <span class="Apple-converted-space"> </span></p> <span class="Apple-converted-space"> </span><input type="submit" value="Submit" /> } |
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] public ActionResult Save(Person model) { _personRepo.Save(model); return RedirectToAction("Index"); } |
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 |
public void Save(Person person) { // if there is no ID, then assume this is a "new" person // and assign an ID if (string.IsNullOrEmpty(person.Id)) person.Id = "Person::" + Guid.NewGuid(); _context.Save(person); } |
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 = new Document { Id = "Person::" + person.Id, Content = person }; _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 |
@Model.Name @Html.ActionLink("[Edit]", "Edit", new {id = Model.Id.Replace("Person::", "")}) @Html.ActionLink("[Delete]", "Delete", new {id = Model.Id.Replace("Person::", "")}, new { @class="deletePerson"}) |
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 |
public ActionResult Edit(Guid id) { var person = _personRepo.GetPersonByKey(id); return View("Edit", person); } |
Estoy reutilizando la misma vista Edit.cshtml, pero ahora necesito añadir un campo oculto para guardar el ID del documento.
|
1 2 |
<input <span class="hljs-built_in">type</span>=<span class="hljs-string">"hidden"</span> name=<span class="hljs-string">"Id"</span> value=<span class="hljs-string">"@Model.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 |
[DocumentTypeFilter("Person")] public class Person { public Person() { Type = "Person"; } [Key] public string Id { get; set; } public string Type { get; set; } public string Name { get; set; } public string Address { get; set; } public string PhoneNumber { get; set; } public List FavoriteMovies { get; set; } } |
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 class="hljs-tag"><<span class="hljs-title">div</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"panel-body"</span>></span> @Model.Address @if (!string.IsNullOrEmpty(Model.PhoneNumber)) { <span class="hljs-tag"><<span class="hljs-title">br</span> /></span> @Model.PhoneNumber } @if (Model.FavoriteMovies != null && Model.FavoriteMovies.Any()) { <span class="hljs-tag"><<span class="hljs-title">br</span>/></span> <span class="hljs-tag"><<span class="hljs-title">h4</span>></span>Favorite Movies<span class="hljs-tag"></<span class="hljs-title">h4</span>></span> <span class="hljs-tag"><<span class="hljs-title">ul</span>></span> @foreach (var movie in Model.FavoriteMovies) { <span class="hljs-tag"><<span class="hljs-title">li</span>></span>@movie<span class="hljs-tag"></<span class="hljs-title">li</span>></span> } <span class="hljs-tag"></<span class="hljs-title">ul</span>></span> } <span class="hljs-tag"></<span class="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 |
public ActionResult Delete(Guid id) { _personRepo.Delete(id); return RedirectToAction("Index"); } |
...y un nuevo método de repositorio:
|
1 2 3 4 5 |
public void Delete(Guid id) { _bucket.Remove("Person::" + 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.