A repository is a design pattern that separates a data source from its associated business logic by encapsulating the data access details. Repositories translate the underlying data representation into an entity model that fits the problem domain. For example, a repository can translate a SharePoint list item into a business entity such as a product detail record. For more information about the repository pattern, see The Repository Pattern.
The SharePoint Guidance Library includes classes that help you to implement repositories for SharePoint lists. Accessing SharePoint lists with a repository makes it easier to reuse, maintain, and test your code. The following are some of the benefits of using repositories with SharePoint lists.
- Centralized logic for accessing the data store eliminates data dependencies in your business logic. The application has a single implementation for common list-access operations instead of having this code repeated throughout the business logic. This saves development effort.
- Encapsulating the SharePoint list access details reduces the likelihood that developers will write code that has poor performance or unacceptable security characteristics. It is recommended that an experienced infrastructure team write repositories that can be used by the rest of the development team. Accessing lists often requires SharePoint object model methods that must be used very carefully. For more information about working with the SharePoint object model, see Best Practices: Common Coding Issues When Using the SharePoint Object Model on MSDN.
- Repository implementations are replaceable for purposes such as unit testing and sustained engineering. For example, a unit test framework can substitute the implementation of the repository class with a mock object or stub in order to test the application's business logic in isolation. Also, if you decide later to reengineer your application to use a different data source, you only need to replace the repository. It is also recommended that you use the service locator pattern to make the repository implementation easier to replace.
The SharePoint Guidance Library uses composition instead of class inheritance for list repositories. The library has helper classes that you invoke from within your own repository implementation. This gives more flexibility in how you build repositories because you do not need to derive from a particular base class that is provided by the library. Your repository can use any base class you choose or no base class at all.
The following diagram shows a typical repository that is based on the SharePoint Guidance Library.
Repository based on the SharePoint Guidance Library
In this model, business logic retrieves a repository implementation through the service locator. The service locator maps the requested repository interface to a concrete type and creates an instance of that type.
The business logic uses an interface to invoke the operations that are provided by the repository. These operations retrieve and store strongly-typed entities that correspond to SharePoint list items. The repository can also include methods that retrieve a set of business entities based on user-provided selection criteria.
The ListItemFieldMapper and CAMLQueryBuilder helper classes that are provided by the SharePoint Guidance Library simplify the repository implementation. These classes help to translate between the list item and the business entity and to query the underlying list for information. The following are the classes:
CAMLQueryBuilder. This class has methods for the most commonly used filter expressions. You can either filter by content type or use field-matching filters. This eliminates the need to write Collaborative Application Markup Language (CAML) for these conditions. For expressions that are more complex than "is equal to" and "is not equal to," you can add additional filters by using CAML to specify query constraints. Multiple filter expressions are always applied as an AND condition by the CAMLQueryBuilder class.
The CAMLQueryBuilder class is a simple implementation that works well for many cases. If you need more complex query support and do not want to write CAML, there are open source implementations such as the .NET Framework class library CAML.NET or U2U CAML Query Builder, with which you can create the CAML queries interactively. For more information, see Useful Development Tools.
ListItemFieldMapper. This class converts strongly-typed business entities to and from SPListItem objects. It specifies the fields in the SPListItem object that map to properties in the business entity. The ListItemFieldMapper class then uses this mapping to create and populate business entity values from the SPListItem object or to update an SPListItem object from values in a business entity.
The following diagram demonstrates the structure of a SharePoint list repository in the Partner Portal application.
Structure of a SharePoint list repository
The repository implementation uses an SPListItem object from the SharePoint object model to access data. This object is an untyped representation of an item in a list. With this approach, an SPListItem can represent any type of tabular information that is similar to a data row in a database. The repository translates this untyped representation into a strongly-typed class such as the Partner Portal's Incident object. The internal logic of the repository maps the untyped SPListItem objects to the strongly-typed business entities and back again.
The following topics describe the helper classes and show how to use them:
- Key Scenarios. This section explains common situations for using the repository helper classes.
- List Repository Design. This section explains the design and implementation of the repository helper classes.
- Development How-to Topics. This section gives step-by-step examples of how to use the repository helper classes to implement a SharePoint list repository class of your own.
The implementation of the classes is located in the Microsoft.Practices.SPG.Common assembly and the Microsoft.Practices.SPG.Common.ListRepository namespace.