En el anterior post de la serie os comentaba: “En los próximos posts veremos dónde se almacenan REALMENTE estos ficheros, cómo visualizarlos, y lo más importante de todo, cómo editarlos y guardarlos otra vez en la base de datos de forma transparente para el usuario.”
Dicho y hecho. Vamos a dar una ojeada al servidor SQL para ver dónde se almacenan estos ficheros. Recordar que al crear la base de datos debemos especificar un FILEGROUP explícitamente para el almacenamiento FILESTREAM:
CREATE DATABASE Archive
ON
PRIMARY ( NAME = Arch1,
FILENAME = 'c:\data\archdat1.mdf'),
FILEGROUP FileStreamGroup1 CONTAINS FILESTREAM( NAME = Arch3,
FILENAME = 'c:\data\filestream1')
LOG ON ( NAME = Archlog1,
FILENAME = 'c:\data\archlog1.ldf')
GO
El ejemplo anterior crea una estructura de carpetas y ficheros en la ubicación especificada del servidor SQL. Observar que no tiene porque ser la misma que los ficheros MDF y LDF, es más, para escenarios de alto rendimiento no os lo aconsejo precisamente.
Si damos una vistazo a esa estructura veremos que por defecto se crea un fichero filestream.hdr y una carpeta $FSLOG. El primero contiene los metadatos para el contenedor de los datos y el seguindo es el equivalente del log de transacciones de una base de datos. Pura magia!

En nuestro caso, aparece además una carpeta por cada entidad o tabla que contiene campos binarios con almacenamiento FILESTREAM. Como me he decicado a insertar varios documentos de pruebas en la tabla que creamos previamente (unos 1.500 para probar), la carpeta contiene una lista de ficheros similar a esto:

Estos ficheros no tienen extensión ni ningún tipo de vínculo con el documento original. Por eso es importante guardar en la tabla algunos de los metadatos del fichero original, ya que si no es imposible saber que tipo de documento es, ni como visualizarlo (ni mucho menos editarlo). También es importante resaltar que estos ficheros no pueden ser accedidos directamente a través de la red local. A todos los efectos los datos es como si estuviesen físicamente dentro de la tabla, en el fichero MDF.
Las grandes ventajas de este enfoque respecto a la alternativa ‘clásica’ de almacenar sólo la ruta de acceso a los documentos, y tener éstos en una ubicación de red son a mi juicio:
-
Atomicidad: Al fin tenemos un mecanismo que asegura que un registro y un fichero NTFS van a comportarse como una sola entidad, garantizando plenamente su integridad, olvidándonos de mecanismos de sincronización (con todo lo que conlleva).
-
Seguridad: La seguridad se gestiona desde SQL Server, con los usuarios y roles de SQL Server (independientemente de si usamos seguridad integrada o de SQL Server). Podemos olvidarnos de crear listas ACL separadas para controla los accesos a los ficheros NTFS.
-
Backups: Esto no se paga con dinero. Adios a tener que programar copias separadas de la base de datos y de los ficheros. Ahora al realizar un backup, SQL Server copiarà de forma automática la estructura de carpetas (y la restaurará, que es lo más importante).
Pero no todo son ventajas, os recomiendo dar una ojeada a la Tabla 1 de este artículo, que nos ofrece una comparativa muy detallada entre los 3 modelos (Filesystem, varbinary(max) y FILESTREAM).
Por ejemplo, una de las cosas que es muy sencillo hacer es la visualización y edición de los documentos, cuando éstos están almacenados en una ubicación de red accesible por los usuarios de la aplicación. Si sabemos la ruta de acceso al fichero basta hacer un Process.Start y éste se abrirá con la aplicación asociada:
private void editDocument(string filename)
{
Process.Start(filename);
}
Sin embargo utilizando almacenamiento FILESTREAM esto no es tan evidente… Pero eso lo dejo para el siguiente post.
Nos leemos pronto! :-)