Uno de los grandes males con los que nos enfrentamos a la hora de desarrollar cualquier aplicación de SharePoint, es la perdida de memoria o la lentitud en nuestros desarrollos. Estos problemas, muchas veces son producidos porque son nuestros primeros pasos en la plataforma o bien, porque tenemos malos hábitos en nuestra forma de programar. Doy por supuesto que tenemos las infraestructuras adecuadas 🙂
Muchas veces hacemos hincapié en hacer uso de determinados plugins/herramientas que nos hacen la vida más fácil, pero si nosotros no cambiamos nuestra forma de programar o pensar, tendremos trabajo doble. Además, en algún momento en el que esta herramienta proponga algo que no es conveniente nosotros, lo cambiaremos creyendo que es la mejor opción. Estas herramientas están muy bien pero debemos entender el funcionamiento de las mismas para poder decidir si o no a lo que nos proponen, porque si algo falla en el desarrollo no le vamos a echar la culpa al plugin que nos hemos instalado no?
Aspectos básicos: SPQuery
Lo primero es que tenemos que saber cómo hacer las consultas sobre las listas de SharePoint. Para ello, tenemos que conocer todas las utilidades que tenemos que poner en el SPQuery: una muy mala practica es crear este componente y solamente indicarle la consulta que queremos realizar. Esto puede funcionar bien siempre que tengamos un avión de servidor o una lista con pocos datos, pero a todos los efectos estamos cargando el servidor con una petición innecesaria.
El modo «correcto» y más eficiente es, por un lado, indicar el número de campos que queremos visualizar y, por otra parte, indicar el número de elementos que queremos que nos devuelva la consulta. ¿Por qué es mejor? Imaginaros que estamos haciendo una consulta sobre una tabla de 1000 campos y 1000000 de registros, queremos traer el primer registro y consultar el campo nombre y el campo apellidos. ¿A que la consulta SQL que hacéis no es «SELECT * FROM Tabla»?
El código que deberiamos de poner es el siguiente:
var query= new SPQuery { Query = "<Where>...</Where>", RowLimit = 100, ViewFields = "<FieldRef Name='Title' /><FieldRef Name='Apellidos' />" };
Dentro del objeto SPQuery también hay otra propiedad «interesante» y que debemos de conocer que es «QueryThrottleMode». Esta propiedad la podemos modificar en algunas circunstancias para poder permitir hacer consultas sobre listas que tienen más de 8.000 items (siendo 8.000 el valor que tiene por defecto). Por lo general, una mala práctica es elevar los permisos sobre la lista, y posteriormente hacer la consulta. A nivel de «eficiencia» sera lo mismo, pero no a nivel de seguridad. El hacer uso del RunWithElevatePrivilegies debe de ser en circunstancias excepcionales porque si un usuario no es Administrador es por algo, ¿no?
Otra forma de acceder a listas con un gran volumen de datos es haciendo uso del ContentItereator, una utilidad que salio en SharePoint 2010, con la finalidad de que se puedan consultar elementos de listas grandes.
Otro aspecto a comentar, es cómo podemos acceder a los siguientes 100 elementos. De una forma muy sencilla: cuando lanzamos la consulta, nos devuelve un SPListItemPosition que lo que hace es darnos la posición de los siguientes elementos. Estos valores nos lo debemos guardar y pasarlos en la siguiente consulta. De esta forma, estaremos paginando y consultando eficientemente sobre la lista de SharePoint.
Entendiendo el acceso/consulta y dispose/no dispose de los SPSite,SPWeb y SPContext
Otro de los típicos fallos que cometemos es que, cuando vamos a realizar cualquier consulta a SharePoint, empezamos a utilizar new SPSite(‘…’). Esto lo que hace es crearnos una nueva conexión, y si ademas, después no disposamos la conexión, dejamos una conexión sin cerrar en el servidor. Esto por cada desarrollo va creciendo hasta que decimos SharePoint no vale para nada ¿no? Y el problema no es de SharePoint, el problema es que nos estamos equivocando nosotros en la forma de desarrollar. Os pongo un símil: ¿a que no conduciríais un coche que fuera perdiendo gasolina? Seguro que diríamos que este coche consume una barbaridad, pues con SharePoint es algo parecido.
Tras esta primera reflexión, no es que no tengamos que utilizar un new SPSite (quizás sí) pero debemos de reflexionar cuándo utilizarlo. Por ejemplo, si yo quiero sacar los usuarios que tiene el Site donde estoy, pues lo mejor de todo es utilizar el SPContext. El SPContext nos muestra información que ya tiene del sitio y como ya la ha solicitado a la base de datos pues su acceso es más rápido. Pero eso no es todo: cuando accedemos al SPContext no podemos ni debemos disposar este elemento. ¿Porqué? Porque si eliminamos el contexto sencillamente nos cargamos la Web de ahí su peligrosidad. Pero es como todo un gran poder, que conlleva una gran responsabilidad.
Otro aspecto que cuando utilizamos los objetos es que debemos de disposarlo, bien explicitamente o bien haciendo uso de los using. Ejemplo:
using (var spSite = new SPSite(SPContext.Current.Site.ID)) { using (var spWeb = spSite.OpenWeb()) { ................ } }
Un post de obligada lectura es el del Maestro David Martos en el que todos estos aspectos los deja bastante bien resueltos.
Cachear la información
Uno de los aspectos que más penaliza el rendimiento es cada vez que SharePoint debe consultar a la Base de Datos. Por este motivo, una de las buenas practicas que indica Microsoft es cachear las consultas realizas. Podéis consultar estas buenas practicas en este link
Yo considero que es una buena practica cachear la información, pero siempre en su justa medida, por ejemplo, si yo tengo una pantalla que muestra información dependiendo del usuario, me parece una tontería tenerla cacheada ya que con mucha probabilidad la siguiente persona que me solicite esta información no sera el usuario, con lo cual tenemos doble perdida (la inserción en la cache + la consulta al SQL). Mi consejo a la hora de cachear la información es ver cuál es la información que menos cambia y más se consulta, o por ejemplo, tengo una lista de Clientes que se usa mucho en muchas partes de mi desarrollo, pues esa tiene todas las papeletas para almacenarla en cache.
Otro aspecto que tenemos que tener en cuenta es la duración que va a tener esta cache, el intervalo que mostremos va a ser muy importante porque dependiendo de esta información es posible que no se esté visualizando la información correcta.
Cachear es muy buena opción, pero un mal uso de la cache quizás sea perjudicial.