RavenDB(III) Sobre la metadata y la serialización de los documentos

En esta tercera de las entradas sobre RavenDB, si lo deseas puedes consultar las entariores aquí y aquí, intentaremos continuar el trabajo dónde lo dejamos, es decir, profundizando acerca del concepto y el trabajo con lo documentos. Como ya hemos podido ver, RavenDB utiliza una serie de convenciones para trasladar nuestros tipos .NET ( incluídos dinámicos y anónimos ) a un payload que enviar por HTTP. Este proceso tiene dos partes importantes, la primera es la de obtención y creación de la metadata y la segunda la obtención del contenido de la entidad que será almacenada como un documento en la base de datos. A lo largo de esta entrada veremos como se realizan ambas tareas y sobre todo como podemos cambiar o ampliar su funcionamiento.

 

La metadata

En la anterior entrega ya vimos como RavenDB dispone de una serie de convenciones que nos permitían decidir como extrar información de metadata, en concreto, vimos como disponemos de una convención llamada FindTypeTagName gracias a la cual podríamos modificar como se obtenía el valor de Raven-Entity-Name, propiedad de la metadata de un documento por defecto. A mayor de esta propiedad, RavenDB incluye en la metadata la información del tipo .NET que se ha utilizado para serializar el documento en la propiedad Raven-Clr-Type, el valor de esta propiedad en realidad es meramente informativo, es decir, se podría modificar el tipo ( nombre ,namespace etc ) y cargarse perfectamente después aunque el valor de Raven-Clr-Type ya no sea coincidente. Al igual que con Raven-Entity-Name la forma de obtener el tipo de un documento también se puede modificar facilmente, como para el caso anterior, en nuestro DocumentStore.Conventions tendremos el método FindClrTypeName al cual le podremos asignar el delegado que se ejecutará para obtener este valor. Un ejemplo de implementación podría ser el siguiente:

 


 

Por supuesto, ver o cambiar las propiedades actuales de la metadata no es lo único que nos puede interesar. Otra tarea importante es la de poder agregar nuevos elementos a esta metadata, bien para realizar alguna extensión de RavenDb, muchos bundles usan esto, o para poder posteriormente hacer algún índice de consulta que use esta información. Agregar información a la metadata de un documento se puede hacer de diferentes formas, iremos viendo estas en los siguientes puntos:

 

Metadata de forma explícita

 

Cualquier session de RavenDB pone a nuestra disposición un método para obtener y manipular la metadata de un documento. En concreto, el método GetMetadataFor que tenemos disponible en las operaciones de una sesión nos permite obtener un RavenJObject con esta información. En el siguiente tip de código podemos ver esto:

 


Estos objetos RavenJObject no son más que, en un principio, pares de clave/valor  sobre los que podemos interactuar de una forma sencilla como podemos ver en el siguiente tip de código, en el que incluímos una nueva propiedad de metadata.

Untitled


Por supuesto, si nos vamos a nuestro Raven Management Studio podremos ver como esta nueva propiedad de metadata forma parte de nuestro documento, tal y como nos muestra la imagen anterior.

 

Metadata con Listeners

 

RavenDB nos proporciona un mecanismo de listerners similar, en concepto no tanto en propósito, al que tenemos en NHibernate con los event listeners.  Para registrar un listener con RavenDB solamente tenemos que hacer uso del método RegisterListener que nos proporciona la clase DocumentStore, ojo que es explícitamente la implementación y no la interface IDocumentStore. Me imagino que esto es intencional para promocionar el registro y la inicialización en un punto, aunque lógicamente esto habría que preguntarselo al creador. Un listener, no es más que cualquier clase que implemente el contrato IDocumentConversionListener. En las siguientes lineas se puede ver la inicialización de un DocumentStore con un Listener y el esqueleto del mismo.

 


 

Visto esto, si quisiéramos hacer lo mismo que en el caso anterior sería tan simple como lo siguiente:

 


 

La serialización

 

Bien, llegados hasta aquí ya sabemos como se obtiene la metadata de cada uno de los documentos, a mayores, también sabemos incluso los mecanismos que tenemos para modificar esa metadata si queremos agregar información personalizada y, también, cuales son las convenciones que tenemos por defecto. Ahora llega la hora de entender cuales son los miembros de un tipo que se utilizan para formar los documentos de las entidades y, si es posible, como cambiar este comportamiento.  Para hacer este ejercicio vamos a empezar por jugar con una clase que contenga los elementos más habituales en una entidad, propiedades, fields, propiedades de solo lectura, etc etc… la entidad en cuestión es la siguiente:

 


Si hacemos el ejercicio de guardar una instancia de esta clase en realidad el documento contendría la siguiente información:

 

Es decir, RavenDB por defecto solamente incluye los elementos públicos de nuestras entidades, sean propiedades o fields y sean de solo lectura o no las propiedades. Aunque esto está bien, la verdad, es que en muchísimos escenarios no será correcto, necesario o incluso válido. En muchas ocasiones no queremos que algunas propiedades se serializen, como por ejemplo Values, o también que los fields privados sean parte del documento. Por suerte, RavenDB nos ofrece bastantes facilidades para lograr introducir todas nuestras necesidades en cuanto al diseño de los documentos.

 

La primera parte, la de ocultar alguna propiedad o, incluso, hacer que el nombre de la propiedad en el documento no se corresponda con la propiedad de la entidad puede hacerse fácilmente utilizando una serie de atributos, al igual que, por poner un simil, podemos hacer en MongoDB con BsonDocument, BsonElement etc. En realidad, estos atributos son los definidos por JSON.NET, dependencia de RavenDB para el tema de serialización/deserializacion JSON/.NET. En el siguiente tip de código podemos ver como ignorar la propiedad Values y modificar el nombre de nuestro field publico.

 


 

Con lo que el documento quedaría de la siguiente forma:

 

Bien, la primera parte ya la hemos tratado, ahora quizás queda en principio la más complicada y es, decirle a RavenDB como tiene que resolver estos contratos de entidad,  usar fields privados etc etc…. Por suerto, como siempre hasta ahora, tenemos un punto de trabajo. En RavenDB, la resolución de las entidades, que elementos formarán parte de los documentos se hace por medio de un contrato llamado IContractResolver.  La implementación por defecto que RavenDB nos ofrece es DefaultRavenContractResolver y la misma puede agregarse facilmente desde nuestro DocumentStore.

 

Con el fin de lograr nuestro objetivo vamos a hacer una nueva implementación de IContractResolver y, para ahorrarnos tiempo y trabajo la vamos a hacer partiendo de la implementación por defecto,DefaultContractResolver, ojo no es DefaultRavenContractResolver.. Asi, si queremos serializar miembros privados solamente tendríamos que hacer lo siguiente:

 


 

Bueno, creo que por ahora es bastante, hay que dejar para las siguientes entradas… ¿Preguntas?

 

Saludos

Unai

2 comentarios en “RavenDB(III) Sobre la metadata y la serialización de los documentos”

  1. “en la propiedad Raven-Clr-Type, el valor de esta propiedad en realidad es meramente informativo, es decir, se podría modificar el tipo ( nombre ,namespace etc ) y cargarse perfectamente después”

    Con esto me queda claro lo que preguntaba en el post anterior. Gracias!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *