Obtener Información de los Perfiles de Usuario en SharePoint y no Morir en el Intento

El servicio de perfiles de usuarios almacena la información en una ubicación central, a la que podemos acceder desde la propia administración de SharePoint. No obstante, si queremos acceder a través de código podemos encontrarnos con ciertos problemas, siendo la velocidad uno de los principales inconvenientes.
En un rango bajo (1-50 usuarios) no tenemos dificultades, nos basta con acceder a través del modelo de objetos o por WebServices, pero cuando el rango aumenta y trabajamos del orden de 5.000-10.000 usuarios nos vemos afectados por una bajada de rendimiento que provoca timeouts en la página.
A continuación veremos dos formas de obtención de perfiles, cada una referente a un tipo de volumen de datos.
Modelo de Objetos
El acceso a través del modelo de objetos se hace con la API de SharePoint. Se puede utilizar tranquilamente cuando trabajamos con pocos perfiles pero su funcionalidad es inversamente proporcional a la cantidad de usuarios, por lo que con un rango muy grande de usuarios nos podemos encontrar con problemas de eficiencia temporal.
Si queremos utilizar este método, en primer lugar debemos trabajar con privilegios elevados que nos permitirán acceder a todo lo que necesitemos.

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    //Aquí irá nuestro código
}

Después debemos acceder al sitio web a través del objeto SPSite y obtener el contexto de dicho Site.

using (SPSite site = new SPSite(/*Our WebSite*/))
{
    ServerContext context = ServerContext.GetContext(site);
    HttpContext hContext = HttpContext.Current;
    if (HttpContext.Current != null)
    {
        if (hContext.Items["HttpHandlerSPWeb"] == null)
            hContext.Items["HttpHandlerSPWeb"] = site.RootWeb;
        if (hContext.Items["Microsoft.Office.ServerContext"] == null)
            hContext.Items["Microsoft.Office.ServerContext"]=context;
    }
    //Aquí irá nuestra consulta
}

Por último, podemos realizar una consulta LINQ que nos busque un usuario concreto. Por ejemplo, podemos buscar el usuario con el nombre de cuenta que le pasemos (en este caso “searchUser”).

lstUserP = (from f in (new UserProfileManager(context)).OfType() where f[PropertyConstants.AccountName].Value.ToString().Contains(searchUser) select f).ToList();

Búsqueda de SharePoint
Si trabajamos con una lista extensa de usuarios (por ejemplo, cinco mil), el anterior método no nos sirve y debemos encontrar otra forma rápida de acceder a dichos datos. Mi propuesta es hacerlo a través de la propia búsqueda de SharePoint. El motivo es sencillo, cuando accedemos a la administración de SharePoint y consultamos los perfiles el resultado la carga de la página es como cualquier otra, sin grandes tiempos de espera, por lo que si podemos utilizar el mismo método que usa SharePoint internamente significa que podemos obtener los perfiles sin perder eficiencia. LA pregunta es: ¿Cómo lo hacemos?
En primer lugar debemos construir una consulta que busque en el Scope correspondiente (en este caso nos interesan los perfiles de usuario), lo haremos con un StringBuilder.

StringBuilder queryText = new StringBuilder();
queryText.Append("SELECT AccountName, FirstName, WorkEmail ");
queryText.Append("FROM SCOPE() ");
queryText.Append("WHERE "scope" = 'People' ");

En esta consulta hemos especificado la cuenta, el nombre y el email pero se pueden añadir más propiedades, siempre que estén definidos en los perfiles (ya sean propios de SharePoint o los hayamos añadido nosotros).
Después debemos generar una Query de búsqueda del tipo FullTextSqlQuery de la librería de búsqueda de Microsoft (Microsoft.Office.Server.Search.Query). La crearemos indicando nuestro webSite, el tipo de resultado, asignando la consulta que hemos creado antes, y especificando el límite de filas que queremos. Quedaría así:

Microsoft.Office.Server.Search.Query.FullTextSqlQuery query = new Microsoft.Office.Server.Search.Query.FullTextSqlQuery(new SPSite(/*Nuestro Site*/));
query.QueryText = queryText.ToString();
query.ResultTypes = Microsoft.Office.Server.Search.Query.ResultType.RelevantResults;
query.RowLimit = 50000;

Llegados a este punto lo tenemos todo listo para ejecutar la consulta, que nos devolverá un ResultTableCollection que podemos convertir a DataTable en pocos pasos:

Microsoft.Office.Server.Search.Query.ResultTableCollection results = query.Execute();
ResultTable resultTable = results[ResultType.RelevantResults];
DataTable table = new DataTable();
table.Load(resultTable);

Y a partir del DataTable podemos desarrollar lo que necesitemos para los perfiles (convertirlo a una lista, utilizarlo como fuente de datos para una Grid…).

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.