SharePoint 2010: Limitaciones en campos proyectados al hacer Joins!

Como sabéis, una de las novedades que incorpora SharePoint 2010 es la posibilidad de hacer Joins en las consultas que hagamos a listas que están relacionadas mediante campos de lookup con otras listas. Este soporte es posible gracias a la actualización del esquema CAML subyacente, de forma que podemos incorporar Joins a nuestras consultas ya sea en CAML o utilizando LINQ To SharePoint (el proveedor se encarga de generar el código correspondinte). Así por ejemplo:

  • En el caso de usar un objeto SPQuery, podemos definir un Join en CAML de la siguiente forma (en este caso tenemos una lista Projects que está relacionada mediante un campo de lookup con la lista Employees…el ejemplo está tomado del Training Kit de desarrollo de SharePoint 2010):
   1: using (SPSite siteCollection = new SPSite("http://demo2010a:100"))

   2: {

   3:     SPList list = siteCollection.RootWeb.Lists["Projects"];

   4:  

   5:     SPQuery query = new SPQuery();

   6:     query.Joins =

   7:         @"

   8:         <Join Type='LEFT' ListAlias='Primary_x0020_Contact'><!--List Name: Employees-->

   9:             <Eq>

  10:                 <FieldRef Name='Primary_x0020_Contact' RefType='ID' />

  11:                 <FieldRef List='Primary_x0020_Contact' Name='ID' />

  12:             </Eq>

  13:         </Join>

  14:         ";

  15:     query.ProjectedFields =

  16:         @"

  17:         <Field Name='Primary_x0020_ContactTitle' Type='Lookup' List='Primary_x0020_Contact' ShowField='Title' />

  18:         <Field Name='Primary_x0020_ContactJobTitle' Type='Lookup' List='Primary_x0020_Contact' ShowField='JobTitle' />

  19:         ";

  20:     query.ViewFields =

  21:         @"

  22:         <FieldRef Name='Title' />

  23:         <FieldRef Name='Primary_x0020_ContactTitle' />

  24:         <FieldRef Name='Primary_x0020_ContactJobTitle' />

  25:         ";

  26:     query.Query =

  27:         @"

  28:         <Where>

  29:             <Eq>

  30:                 <FieldRef Name='Primary_x0020_ContactTitle' /><Value Type='Lookup'>Contact1</Value>

  31:             </Eq>

  32:         </Where>

  33:         ";

  34:     Console.WriteLine("CAML Query sent");

  35:     Console.WriteLine(query.ViewXml.ToString());

  36:     Console.ReadLine();

  37:     Console.WriteLine("Query results");

  38:     SPListItemCollection results = list.GetItems(query);

  39:     foreach (SPListItem item in results)

  40:     {

  41:         Console.WriteLine("{0} - {1} - {2}",

  42:             item["Title"].ToString(),

  43:             item["Primary_x0020_ContactTitle"].ToString(),

  44:             item["Primary_x0020_ContactJobTitle"].ToString());

  45:     }

  46: }

  • Como veis, el objeto SPQuery incorpora dos nuevas propiedades:
    • Joins, que permite definir el join o joins en la consulta.
    • ProjectedFields, que permite incorporar en los resultados devueltos campos proyectados, es decir, campos que están en la lista relacionada con la lista principal. En este caso estamos devolviendo dos campos de la lista Employees.
  • En el caso de usar LINQ To SharePoint, el uso de Joins es mucho más intuitivo. Por ejemplo:
   1: try

   2: {

   3:     SPLINQProxySiteDataContext ctx =

   4:         new SPLINQProxySiteDataContext(SPContext.Current.Web.Url);

   5:     var productsList = from p in ctx.Productos

   6:                        select new

   7:                        {

   8:                            Producto = p.Título,

   9:                            Descripcion = p.Descripción,

  10:                            Fabricante = p.Fabricante.Título

  11:                        };

  12:     ctx.Log = swWriter;

  13:     grdProductos.DataSource = productsList;

  14:     grdProductos.DataBind();

  15:     txtConsultaCAML.Text = "Consulta: " +

  16:         swWriter.ToString();

  17: }

  18: catch (Exception ex)

  19: {

  20:     txtError.Text = ex.Message;

  21: }

  • En  este caso, tras definir una instancia del objeto DataContext correspondiente, estamos haciendo una consulta a la lista Productos que está relacionada con la lista Empresas mediante el campo de lookup Fabricante. En el select realizado estamos consultando dos campos de la lista Productos y uno de la lista Empresas por lo que el proveedor de LINQ To SharePoint generará por nosotros el correspondiente Join (lo podemos ver con ctx.log=swWriter):
   1: <View>

   2:     <Query>

   3:         <Where>

   4:             <BeginsWith>

   5:                 <FieldRef Name="ContentTypeId" />

   6:                     <Value Type="ContentTypeId">0x0100</Value>

   7:             </BeginsWith>

   8:         </Where>

   9:     </Query>

  10:     <ViewFields>

  11:         <FieldRef Name="Title" />

  12:         <FieldRef Name="Descripci_x00f3_n" />

  13:         <FieldRef Name="FabricanteTitle" />

  14:     </ViewFields>

  15:     <ProjectedFields>

  16:         <Field Name="FabricanteTitle" Type="Lookup" List="Fabricante" ShowField="Title" />

  17:         </ProjectedFields>

  18:     <Joins>

  19:         <Join Type="LEFT" ListAlias="Fabricante">

  20:         <!--List Name: Empresas-->

  21:             <Eq>

  22:                 <FieldRef Name="Fabricante" RefType="ID" />

  23:                 <FieldRef List="Fabricante" Name="ID" />

  24:             </Eq>

  25:         </Join>

  26:     </Joins>

  27:     <RowLimit Paged="TRUE">2147483647</RowLimit>

  28: </View>

  • Finalmente, y después de tanto “rollo”, la respuesta a las preguntas que dan título al post:
    • ¿Cuántos Joins podemos tener? La respuesta es que el umbral tope definido (por aplicación web) por defecto es de 8 como podéis consultar en este enlace:http://technet.microsoft.com/en-us/library/cc262787.aspx. Este es el umbral que se fija en la administración central y que se puede sobreescribir ya que no es un valor límite, aunque si el máximo recomendado sin penalizar el rendimiento. Si se intenta realizar una consulta que implique superar este número de Joins por defecto, la consulta se bloqueará y se generará la correspondiente excepción. En este thread de los foros de MSDN podéis encontrar un caso en el que se pudo configurar el uso de 13 Joins antes de obtener la excepción: http://social.msdn.microsoft.com/Forums/en-US/sharepoint2010general/thread/f48f36f8-108f-4ac8-a5d6-c347b7adb5ce. En lo que a realizar consultas simples, sin Joins, SharePoint devolverá en este caso hasta un máximo de 8 campos de lookup.
    • ¿Se pueden hacer Joins con cualquier tipo de campo? La respuesta es que no. Por ejemplo, no se permite hacer un Join con campos que no tienen sentido como los de texto enriquecido.

Publicado por

Juan Carlos González

Juan Carlos es Ingeniero de Telecomunicaciones por la Universidad de Valladolid y Diplomado en Ciencias Empresariales por la Universidad Oberta de Catalunya (UOC). Cuenta con más de 12 años de experiencia en tecnologías y plataformas de Microsoft diversas (SQL Server, Visual Studio, .NET Framework, etc.), aunque su trabajo diario gira en torno a SharePoint & Office 365. Juan Carlos es MVP de Office Servers & Services desde 2015 (anteriormente fue reconocido por Microsoft como MVP de Office 365 y MVP de SharePoint Server desde 2008 hasta 2015), coordinador del grupo de usuarios .NET de Cantabria (Nuberos.Net, www.nuberos.es), co-fundador y coordinador del Grupo de Usuarios de SharePoint de España (SUGES, www.suges.es), así como co-director de la revista gratuita en castellano sobre SharePoint CompartiMOSS (www.compartimoss.com). Hasta la fecha, ha publicado 8 libros sobre SharePoint & Office 365 y varios artículos en castellano y en inglés sobre ambas plataformas.

Un comentario en “SharePoint 2010: Limitaciones en campos proyectados al hacer Joins!”

Deja un comentario

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