We have all looked at where statements all through out code and seen the same .Where() typed 20-30 times through out the code. It seems that when using LINQ we have such an easy time typing expressions and method chains with the fluent API that we have forgotten to obey DRY. ( Don’t Repeat Yourself ) Any line of code that has been written twice is a waste. If writing the same code twice you are stealing, plain and simple! You are stealing away consistency and supportability, and are causing multiple points of change for future changes. Take the following code for example, and keep in mind this is a simple and the problem will be worse in larger code bases.
static void Main(string[] args)
{
_repository = new EntityFrameworkRepository(new AdventureWorksEntities());
_productRepository = new ProductRepository(_repository);
_repository.AsQueryable<Product>().Where(x => x.Class == "Something");
var longRunningProducts = _productRepository.GetLongRunningProducts();
}
public List<Product> GetProducts()
{
return _repository.AsQueryable<Product>().Where(p => p.Class == "Clothing").ToList();
}
public List<Product> GetInventory()
{
var items = _repository.AsQueryable<Product>().Where(p => p.Class == "Clothing").ToList();
//Do Stuff
return items;
}
Now that we are able to look at the problem with open eyes the next question is how do we control this so that there is one place for this logic. The answer is query libraries.
static void Main(string[] args)
{
_repository = new EntityFrameworkRepository(new AdventureWorksEntities());
_productRepository = new ProductRepository(_repository);
_repository.AsQueryable<Product>().Where(x => x.Class == "Something");
var longRunningProducts = _productRepository.GetLongRunningProducts();
}
public IEnumerable<Product> GetProducts()
{
return _repository.GetClothing();
}
public IEnumerable<Product> GetInventory()
{
var items = _repository.GetClothing();
//Do Stuff
return items;
}
public static class ProductQueries
{
public static IQueryable<Product> GetClothing(this IRepository repository)
{
return repository.AsQueryable<Product>().Where(x => x.Class == "Clothing");
}
}
This allows for the control of queries and the usage of them across multiple areas without rewriting the .Where and it’s parameters everywhere. You can parameterize these further to increase reuse. Like so
public static class ProductQueries
{
public static IQueryable<Product> GetClothing(this IRepository repository)
{
return repository.GetByClass("Clothing");
}
public static IQueryable<Product> GetByClass(this IRepository repository, string className)
{
return repository.AsQueryable<Product>().Where(x => x.Class == className);
}
}
11ac2395-c348-42ea-ab92-ba9c6a77e8c2|1|5.0
Entity Framework, Productivity