LINQ to SharePoint and Document Sets

LINQ to SharePoint offers a great alternative to working directly with CAML queries in your SharePoint applications. Documents Sets are a convenient way to allow users to group a set of files together.  One of the challenges I recently had was figuring out how to deal with Document Sets within my LINQ queries. To follow these samples, you’ll want to start by creating a new document library (mine is called Resources) and enabling the Document Set content type on the library.

The first step is to ensure that the “Document Sets” feature is enabled on the Site Collection:

image

Next, create the library (or choose an existing one) and go to the advanced settings. From the advanced settings, set “Allow management of content types?” to “Yes”:

image

Clicking OK will bring you back to the library settings where you can select “Add from existing site content types” in the Content Types section. Add the “Document Set” content type and click “OK.”

image

With the document library setup, we’re ready to run SPMetal to generate the entity classes that will be used by LINQ. SPMetal is run from the command line and is located in the {SharePoint Root}\bin folder:

image

If you;re following along, you should now have a Content.cs file that can be brought into a Visual Studio project.

With all the plumbing done, it’s time to write some code. Let’s start by retrieving a document set based on the title:

public ResourcesDocumentSet GetDocumentSet(string title)
{
     using (Microsoft.SharePoint.Linq.DataContext ctx = new Microsoft.SharePoint.Linq.DataContext(_webUrl))
     {
         EntityList<ResourcesDocumentSet> resources = ctx.GetList<ResourcesDocumentSet>("Resources");
         ResourcesDocumentSet docSet = (from documentset in resources where documentset.Name == title select documentset).First<ResourcesDocumentSet>();
         return docSet;
     }

}

The first step is to create a DataContext and pass in the URL of the site we want to query. ResourceDocumentSet is an entity class that was generated by SPMetal. Remember that Resource was the name of the document library, thus ResourceDocumentSet is one of the entity classes generated. If you look into the generated code, the inheritance chain looks like this: ResourceDocumentSet –> DocumentSet –> DocumentCollectionFolder –> Folder –> Item. It is worth mentioning that in production, you would want to use FirstOrDefault instead of just first but the code demonstrates the concept.

If you examine the ResourceDocumentSet class, you’ll see that it exposes all the properties we would expect on a list item:

image

What it does not expose is any way to get at the documents inside of the Document Set. The trick here is that a Document Set is really just a wrapper around a Folder and a List Item. What we’re looking at above is basically the list item. In order to retrieve the contents of the Document Set, it is necessary to use the ScopeToFolder method:

public IQueryable<ResourcesDocument> GetDocumentsInSet(string setName)
{
     using (DataContext ctx = new DataContext(_webUrl))
     {
         DocumentSet docSet = GetDocumentSet(setName);

         EntityList<ResourcesDocument> documentList = ctx.GetList<ResourcesDocument>("Resources");
         var docSetItems = from documents in documentList.ScopeToFolder(docSet.Path + "/" + docSet.Name, true) select documents;

         return docSetItems;
     }
}

Building on the GetDocumentSet method we can then retrieve the contents (an EntityList of ResourceDocument) of the folder represented by the Document Set by limiting our scope to the URL of the document set (aka the folder). As you would expect, each ResourceDocument then exposes Title, Path, ID and other properties.

Hopefully, these examples will save you a little time in dealing with Document Sets and LINQ to SharePoint.

10 comments:

Anonymous said...

What assembly reference I need to use ResourcesDocumentSet class?

Now I get the following error message: "The type or namespace name 'ResourcesDocumentSet' could not be found (are you missing a using directive or an assembly reference?)"

Steve said...

ResourcesDocumentSet is one of the classes generated by SPMetal. Check the namespace on the generated CS file and include that.

k.anantharengan said...

thanks a lot

Anonymous said...

Hi Steve, Could I use also Insert and Delete methods from context, if yes please provide the example.

k.anantharengan said...

Hi steve I am having a custom document library named 'Product' and I am having custom content type named 'ProductSet' and this content type had been set as the default content type for the 'Product' document library . When I produced Linq to SP entities using SPMetal.exe it does not generate me any class named 'ProductProductSet' , so that I can query through the document library (Product)to get the document sets of content type (Product Set). Can you give me your suggestion on how to query only the document sets that are present inside a custom document library

k.anantharengan said...

Hi steve I am having a custom document library named 'Product' and I am having custom content type named 'ProductSet' and this content type had been set as the default content type for the 'Product' document library . When I produced Linq to SP entities using SPMetal.exe it does not generate me any class named 'ProductProductSet' , so that I can query through the document library (Product)to get the document sets of content type (Product Set). Can you give me your suggestion on how to query only the document sets that are present inside a custom document library

Himani Sharma said...

I think it should be ResourcesDocument and not ResourcesDocumentSet as the name of the document library generated via SPMetal.

Steve said...

Hi k.anantharengan,

One of my co-workers suggested that you try adding a document of that new content type before running SPMetal. He's experienced issues with SPMetal ignoring content types that have not actually been used yet.

K.Anantharengan said...

Thanks a lot.

rama700 said...

Hi Steve;
i am follwoing your post and generaged Class through SPMetal.
after adding class to project unable to find ResourcesDocumentSet Class reference. fyi: i already added namespace.