-
Notifications
You must be signed in to change notification settings - Fork 0
LinqExtensions
The MvcBlanketLib adds new LINQ extension methods overloads to simplify tasks of filtering and sorting data. These extension methods overloads include:
- Where
- OrderBy
##Where extension method overloads
This new overload is defined in MvcBlanketLib.PageFilters
namespace and is designed to simplify tasks of filtering data requested from the storage.
Let's assume we have the table that contains two columns we want to be able to filter onto.
CREATE TABLE Product
(
ProductId uniqueidentifier NOT NULL PRIMARY KEY,
Title nvarchar(max) NOT NULL,
Price int NOT NULL
)
We want to be able to filter products by Title and Price columns, so we render onto the HTML page two text boxes, so user can enter required conditions into them. In classic approach we could use switch case
construct to compose something like that:
public IQueryable<Product> GetProducts(string title, int? price)
{
IQueryable<Product> products = Context.Products;
if (!string.IsNullOrWhiteSpace(title))
{
products = products.Where(p => p.Title.StartsWith(title));
}
if (price != null)
{
products = products.Where(p => p.Price < price.Value);
}
return products;
}
This approach is not clear to read and is hard to code is case if the number of filters is more than 2 or 3. In addition we have to explicitly define the type of variable products
- IQueryable<>
, because var
statement will cause compile error here as compiler will infer wrong type - DbSet<>
that cannot be used in the following LINQ expressions.
We could improve the situation above by using PageFilter<>
introduced with MvcBlanket. So we rewrite the example above:
public IQueryable<Product> GetProducts(ProductFiltersModel filters)
{
IQueryable<Product> products = Context.Products;
if (filters.Title.Selected)
{
products = products.Where(p => p.Title.StartsWith(filters.Title.Value));
}
if (filters.Price.Selected)
{
products = products.Where(p => p.Price < filters.Price.Value);
}
return products;
}
That's a much better because PageFilter<>
automatically provides support of Selected
property that allows to verify against the exact filter is really used and contains valid data.
But to really simplify the code above we can use the new overload of Where
extension method:
public IQueryable<Product> GetProducts(ProductFiltersModel filters)
{
return Context.Products
.Where(filters.Title, p => p.Title.StartsWith(filters.Title.Value))
.Where(filters.Price, p => p.Price < filters.Price.Value);
}
The Where
method contains additional PageFilter<>
parameter that allows the method to check if filter is selected
and conditionally apply predicate given in the second parameter to the IQueryable
expression.
##OrderBy extension method overloads
This overload is defined in MvcBlanketLib.Extensions
namespace and extends MvcContrib OrderBy
implementation that allows to define ColumnName and OrderDirection as string and enumeration member accordingly without lambda expressions. But MvcContrib implementation does not allow to process consequent sortings by several columns at once, so MvcBlanket fills this gap.
The declaration of method looks like:
public static IQueryable<T> OrderBy<T>(
this IQueryable<T> datasource,
string propertyName,
SortDirection direction,
bool first
)
Additional first
parameter allows to specify either this sort is really first so it will be translated into OrderBy|OrderByDescending
method or not so it will be translated into ThenBy|ThenByDescending
method.
This extension is affectively used in PagedViewModel implementation allowing to sort by multiple columns at once.