Sunday, April 24, 2011

Blog Post: Repository pattern with LINQ to SharePoint DSL Extension (part 2)

In the first part of this tutorial, I explained the basics about the repository pattern implementation in the LINQ to SharePoint DSL Extension for Visual Studio 2010.  In this previous post, I explained how to create a new Repository pattern thanks to a new Visual Studio item. This item uses an existing LINQ to SharePoint data model (l2sp file) to generate automatically a repository pattern implementation. The classes diagram is also available in this previous post.

In this second part, I will explain how to use the object model to call the repository layer in your code with a sample model.

This sample model (the l2sp file) provides the following SharePoint data model:

My data model is called "AdventureWorks" and I added a new "LINQ to SharePoint data model repository" in my Visual Studio project. All the following samples show how to use the generated repository for this model.

How to use the repositories factory

LINQ to SharePoint DSL Extension repository generator generates a factory object context. This factory is an object conception to manipulate operations on the LINQ data context without hard coded references to the concrete type.

The factory is obtained from a static method. You can call this method when you need to get a new factory instance.

For example:

using (IAdventureWorksFactory factory = AdventureWorksFactory.GetNewInstance(SPContext.Current.Web.Url))
{
    //Get a category by id
    Category category = factory.Categories.GetById(2);
    category.Title = "Hello";

    factory.SubmitChanges();
}

 

The factory object provides all the properties and methods to manage the entities repositories. The definition of the factory is very similar to the LINQ to SharePoint DataContext class:

http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.linq.datacontext.aspx

 With the repository implementation, you don’t have a hard coded reference to this data context. The factory object returned by the GetNewInstance method must simply implement the IDataContextFactory interface. With this pattern, you can change tomorrow the complete design of data access layer, by using other data access object implementations. This method is useful when you want to test your business layer with test units based on a non-SharePoint data context.

 The factory instance provides the following things:

  • Methods to manage the data context (similar as DataContext class), for example SubmitChanges, etc.
  • Properties to get repository implementations. For each list in the schema, you have a property to get it. For example:  ICategoriesRepository categories = factory.Categories; The list of repository implementations is similar to the property EntityList<Category> of the DataContext class.

The generated repository classes and interfaces contain:

  • The All property to get the LINQ requestable IQueryable<Category> object
  • The same methods of the EntityList class (like DeleteOnSubmit, etc.)
  • A set of custom generated helpers methods to build LINQ queries on your entities (see more information about helpers in the “Use the helper methods” chapter.

 

Create, Delete and Update methods

When you’re using the repository pattern classes, the “create”, “delete” and “update” operations are similar as the direct LINQ to SharePoint methods.

Create method sample: 

//Get the instance of the repository factory
using (IAdventureWorksFactory factory = AdventureWorksFactory.GetNewInstance(SPContext.Current.Web.Url))
{
    //Get a category by id
    Category category = new Category();
    //or:
    //Category category = factory.Categories.CreateNew();
    category.Title = "New category";
    factory.Categories.InsertOnSubmit(category);
 
    factory.SubmitChanges();
}

 

Update method sample:

using (IAdventureWorksFactory factory = AdventureWorksFactory.GetNewInstance(SPContext.Current.Web.Url))
{
    //Get a category by id
    Category category = factory.Categories.GetById(2);
    category.Title = "Updated category";
   
    factory.SubmitChanges();
}

 

Delete method sample:

//Get the instance of the repository factory
using (IAdventureWorksFactory factory = AdventureWorksFactory.GetNewInstance(SPContext.Current.Web.Url))
{
    //Get a category by id
    Category category = factory.Categories.GetById(2);
    factory.Categories.DeleteOnSubmit(category);
   
    factory.SubmitChanges();
}

 

 

Use the All property to build LINQ queries

When you’re using a repository object, this object is not directly request able.  Bu each repository instance has an “All” property, that implements IQueryable<T>. For example, the ICategoryRepository object instance has a property All of type IQueryable<T>. You can build all the LINQ queries that you want thanks to this object. You can use all the Lambda expression that you want with this property.

 For example:

using (IAdventureWorksFactory factory = AdventureWorksFactory.GetNewInstance(SPContext.Current.Web.Url))
{
    //Get categories queryable object
    IQueryable<Category> all = factory.Categories.All;
   
    //LINQ query
    IQueryable<Category> filteredCategories =
        from t in all
        where t.Version > 2
        orderby t.Version
        descending select t).Take(5);
 
    //Browse results
    foreach (Category category in filteredCategories)
    {
        Console.WriteLine(category.Title);
    }
}

 

Use the helper methods

The LINQ to SharePoint DSL Extension will generate a lot of pre-coded LINQ procedures to manage queries on entities. The principle of this code is to provide methods specialized for all the properties of your entities. These methods and prototypes are useful for the developers to quickly develop code without high skills with Lambda LINQ expressions.

For more information about these helpers methods, please read the first part of this tutorial

Helpers method sample:

using (IAdventureWorksFactory factory = AdventureWorksFactory.GetNewInstance(SPContext.Current.Web.Url))
{
    //First get all the models where the title contains the string "shoes"
    IEnumerable<Model> models = factory.Models.GetWhereTitleContains("Shoes");
 
    //Filter models where the version is greater than 10, ascending by version and limit to 100 elements
    models = Factory.Models.GetWhereVersionIsGreaterThan(models, 10, true, 100);
   
    // Databinds the results data in a data list ASP.Net web control
    if (models == null || models.Count() == 0)
        this.DataListProducts.Visible = false;
    else
    {
        this.DataListProducts.DataSource = models;
        this.DataListProducts.DataBind();
    }
}

 In this previous sample, you can notice than you can combine helper methods thanks to the prototypes with the first IQueryable<T> source argument.

 

To conclude, you can see that when you're using the repository layer code, your code looks like a direct LINQ to SharePoint call. But with this implementation, your code only uses only interfaces of the factory and the repositories, without hard coded references to the LINQ to SharePoint API. This feature is useful to a lot of things, like for example to implement a unit tests layer.   More over, you can use all the generated helpers methods to make queries easily on your model.

In the next part of this tutorial, I will show you how to extend this repository layer and all the advanced settings about it.

Laura Prepon Ashley Scott Michelle Behennah Julie Benz Saira Mohan

No comments:

Post a Comment