In the previous post we looked at how developers have implemented their own repository before coming Linq. The best method which was found is to return of the read-only collection. However, Microsoft introduced Linq and it was the revolution. In this post we will see how developers’ vision changed on implementation the repository pattern.
Many people know that Linq is a tip of an iceberg of changes that 3.0 version has brought. Among which there are extension methods. These methods make it possible to use the IEnumerable<T> interface in new ways. For us most interested are Count<T>() and Any<T>() methods. An example:
var repository = new CountryRepository(session);
var countries = repository.GetCountries(null);
if (countries.Count() > 0)
{
// don't do it!!!
}
if (countries.Any())
{
// do it!!!
}
As you can see the disadvantage of the interface that is associated with impossibility to get the item count is fixed. It should be remembered that the way of correction is the old, Count<T>() simply enumerates the collection and counts the items for you. That may adversely affect the collection with a large number of items. Therefore, the following recommendations:
- Most accurately indicate the filters with which you are requesting information from the repository. I mean, that your every request must be finished by the maximum count of items that need to get. In the presentation layer, so the count is the number of itemss on the page in a control that supports paged view. For example, such control in Silverligth can be DataGrid with DataPager;
- In many scenarios, you don’t need to know the item count, but just to check the collection is empty or not. Instead of comparing the result of Count<T>() with 0, just check the result of Any<T>(). This method won’t count the whole collection, and to return control immediately after the first item.
Agree, the IEnumerable<T> interface became more natural to use as returns a value.
But, along with Linq has another candidate. It is IQueryable<T> interface. It can be seen as an alternative of the IEnumerable<T> interface (it isn’t surprising IQueryable<T>interface is descendant of IEnumerable<T> interface). But this assumption hides one significant difference. The IEnumerable<T> interface is used to iterate through the objects in memory, and the IQueryable<T> - to query the data source and deferred execution. An example:
public class CountryRepository
{
private readonly Entities context;
public CountryRepository(Entities context)
{
this.context = context;
}
public IQueryable<Country> GetCountries()
{
return context.Countries;
}
}
class Program
{
static void Main(string[] args)
{
using (var context = new Entities())
{
var repository = new CountryRepository(context);
var countries = repository.GetCountries().Where(c => c.Name.Contains("a"));
foreach (var country in countries)
{
Console.WriteLine(country.Name);
}
}
}
}
Note, that the query filters and the query results were merged. Moreover, if you’re using a modern ORM getting of values will occur in that place where they actually used. Convenient, isn’t it? So that it is one of the most popular methods. Although it isn’t without disadvantages. Let’s consider the most obvious. What if we call the Count<T>() method after the code described above?
Console.WriteLine(countries.Count());
I think you can answer this question yourself. There will be made a second query to the data source. Unfortunately, we didn’t use the results of the previous query. The solution is also obvious:
class Program
{
static void Main(string[] args)
{
using (var context = new Entities())
{
var repository = new CountryRepository(context);
// We copied query result in memory.
var countries = repository.GetCountries().Where(c => c.Name.Contains("a")).ToList();
foreach (var country in countries)
{
Console.WriteLine(country.Name);
}
Console.WriteLine(countries.Count());
}
}
}
We saved the query results and the second query is already executing to the collection of objects in memory, rather than to the data source. What is important is described case is possible for the team, so if your repositories are implemented this way, it should explain the possible problems other colleagues and make the agreement. But the best option – it is to continue to read this series of posts.




Very good.