Extending the LINQ to SharePoint context to allow additional fields and properties in your queries

Introduction

One of he culprits of working with the LINQ to SharePoint contexts that are being auto-generated for us is that it actually doesn’t necessarily render all the fields or properties you require. For example the built-in fields "Created By" or the "Attachments" property of a list item. Oftentimes we need these fields in our queries, whether they be CAML queries or LINQ queries. With LINQ to SharePoint you have the ability to extend an Entity that you’ve generated, and allow additional code to be executed for those entities. In this article I’ll talk briefly about how you can create and manage an extension to your LINQ context to allow additional fields in your queries.

One of the powerful advantages of doing this is that you post-deployment can extend your queries. Lets for example say that the list in your deployment gets some additional fields in the future, then perhaps you’ll need to make sure that your LINQ context can cope with querying those fields as well – this can easily be done by extending an entity context as I’ll talk about below.

In this article I’ll give you a sample of how to extend the LINQ entity to fit our custom needs, including mapping the "Created By" and "Modified By" fields and some additional logical customizations.

Generate your context

First and foremost we’ll need to generate our context. This can be done using SPMetal (Which you can read more about in this article: Getting Started with LINQ to SharePoint), or for example the extensions in CKS:Dev. I’m going to generate a quick and easy sample for this by utilizing the CKS:Dev tools and then build my samples on top of that.

If you haven’t installed the CKS:Dev tools yet, go right ahead and do that – then get back to this step!

1) Generate a LINQ context by using the CKS:Dev plugin, which will give you this additional context menu in the SharePoint server browser:

This should auto-generate a class file for you, containing all the entities for the selected site:

The file contains all the LINQ to SharePoint data context information that a normal SPMetal.exe command would generate, since this tool in essense is using SPMetal.exe:

As you can see, we’ve easily created the LINQ data context that we need, but unfortunately it’s missing some vital parts for our application – namely some of the built-in fields that you would normally want to work with. In my case, I was lacking the "Created By" and "Modified By" fields and I’d have to find a way to extend the LINQ context to cope with this so my queries can be easily constructed even for those fields.

Extending an entity in your generated LINQ context

In order for us to be able to extend the LINQ context, Microsoft provides us with an interface called ICustomMapping.

We’ll start by inheriting a new class from this interface, and name the class along the lines of the entity we want to extend.

As you can see in my sample above, I not only mapped the two fields I need but I also slightly extended the entity with additional properties for retrieving a clean LoginName from the user-objects. Obviously this can be done using a normal .NET 3.5 extension method on the SPUser object, but here I implemented it in the context to show how it can be easily extended to fit our needs.

Writing a query with our extended data context

So if we’ve followed the very simple steps of creating a new extension for one of our entities, we can now easily access these details from the query we’re writing:

The list contains a few items (all created by the current user, which is the system account – please use your imagination… :-) )

And the results:

Summary

All in all, this gives us the flexibility to customize the way we do our queries in SharePoint using LINQ. I’ve gotten the question about extending LINQ to SharePoint quite a few times over the past years, so I thought it’d be time to reflect those thoughts in this post. I hope you enjoy it and can start utilizing the extension of your LINQ queries!

Nice article, thanks Tobias. ICustomMapping is very useful for a bunch of things. I seem to recall a more simple approach to just getting these basic out of box fields though, something like the following should work:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;