SharePoint 2010: Soporte de Joins en LINQ To SharePoint!

Una de las novedades más destacables de SharePoint 2010 a nivel de desarrollo es por una parte la posibilidad de hacer consultas LINQ a listas y bibliotecas de documentos de un sitio de SharePoint gracias al correspondiente proveedor, y por otra que esas consultas LINQ gracias a la actualización del esquema CAML soportan el uso de Joins y campos proyectados en aquellos escenarios en los que tengamos listas o bibliotecas relacionadas por campos de Lookup (tipo de campo por otra parte también extendido para aprovechar los nuevos campos proyectados del esquema CAML de consultas). La idea de este artículo es precisamente ver como podemos tener varias listas de SharePoint relacionadas y poder realizar consultas que devuelvan información de todas ellas gracias a ese soporte de Joins y de campos proyectados:

  • En el ejemplo propuesto, se disponen de tres listas relacionadas a través de los respectivos campos de Lookup: Empresas, Productos y Versiones de Producto. La lista Productos recoge información de la lista Empresas mediante el campo de Lookup Fabricante y la lista Versiones de Producto recoge información de la lista Productos mediante el campo de Lookup Producto.
  • Si queremos visualizar información de la lista Versiones de Producto en la que mostremos información de la propia lista, pero también de las listas en la jerarquía superior, gracias a LINQ To SharePoint, el soporte de Joins y campos proyectados, basta con definir una consulta como sigue:
   1: var VersionsList = from v in ctx.VersionesProducto

   2:                    select new {

   3:                        Version=v.Title,

   4:                        Producto=v.Producto.Title,

   5:                        Fabricante=v.Producto.Fabricante.Title

   6:                    };

   7:  

   8:                                        

   9: ctx.Log = swWriterCAML;

  10: grdVersiones.DataSource = VersionsList;

  11: grdVersiones.DataBind();

  12: txtConsultaCAML2.Text = "Consulta: " +

  13:     swWriterCAML.ToString();

  • Como vemos, por una parte accedemos a la información de la lista Productos mediante v.Producto.Title y por otra accedemos a la información de la lista Empresas mediante v.Producto.Fabricante.Title…luego los campos de Lookup definidos a cada nivel nos van facilitando el acceso a la información como cabía esperar.
  • La consulta CAML generada en este caso es la siguiente:
   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="ProductoTitle" />

  13:         <FieldRef Name="ProductoFabricanteTitle" />

  14:     </ViewFields>

  15:     <ProjectedFields>

  16:         <Field Name="ProductoTitle" Type="Lookup" List="Producto" ShowField="Title" />

  17:         <Field Name="ProductoFabricanteTitle" Type="Lookup" List="ProductoFabricante" ShowField="Title" />

  18:     </ProjectedFields>

  19:     <Joins>

  20:         <Join Type="LEFT" ListAlias="Producto">

  21:             <!--List Name: Productos-->

  22:             <Eq>

  23:                 <FieldRef Name="Producto" RefType="ID" />

  24:                 <FieldRef List="Producto" Name="ID" />

  25:             </Eq>

  26:         </Join>

  27:         <Join Type="LEFT" ListAlias="ProductoFabricante">

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

  29:             <Eq>

  30:                 <FieldRef List="Producto" Name="Fabricante" RefType="ID" />

  31:                 <FieldRef List="ProductoFabricante" Name="ID" />

  32:             </Eq>

  33:         </Join>

  34:     </Joins>

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

  36: </View>

Precisamente viendo el CAML generado, queda claro una vez más la potencia de usar LINQ To SharePoint en lugar de CAML para consultas con un cierto grado de complejidad ya que el proveedor nos genera una consulta bien formada y además definir la consulta en el entorno de desarrollo con LINQ es altamente productivo. Finalmente, el resultado:

image