Active items and sorting
ALL THE EXAMPLES FROM THIS POST ARE EXTRACTED FROM THE FWKLIGHT DEMO. TO FIND OUT HOW TO GET STARTED WITH THE DEMO, READ THIS POST.
Each query implementation asks you (through abstract methods) how it should bring only the active items and how it should do the sorting.
IT IS YOUR RESPONSABILITY TO IMPLEMENT THESE METHODS WHEN NECCESARY, AND NOT JUST OVERRIDE THEM AND MOVE ON TO SOMETHING ELSE.
Sorting
Sorting is ussualy not critical, but it’s quite important from time to time.
Here are 2 queries which implement sorting by overriding the Sort method:
public class AggregateListQuery1: MultiCriteriaQuery<CustomerOrder1> { private decimal _minPrice; public IList<CustomerOrder1> Execute(ISession session, decimal minPrice) { _minPrice = minPrice; return Load(session); } protected override void ApplyMainFilters(IListMultiCriteriaFetcher<CustomerOrder1> criteria) { criteria.Where(p => p.OrderPrice).Gt(_minPrice); } protected override void FilterOnlyActive(IListMultiCriteriaFetcher<CustomerOrder1> criteria){} protected override void Sort(IListMultiCriteriaFetcher<CustomerOrder1> criteria) { criteria.OrderAscBy(p => p.OrderPrice); } }
public class BonusHistory2ListQuery : LinqQuery<BonusHistory2> { private DateTime _startDate; private DateTime? _endDate; private Client2 _client; public IList<BonusHistory2> Execute(ISession session, DateTime startDate, DateTime? endDate, Client2 client) { _startDate = startDate; _endDate = endDate; _client = client; return Load(session); } protected override void GetMainQuery() { _queryable = from q in _queryable where q.Year >= _startDate.Year && q.Month >= _startDate.Month && q.Client2 == _client select q; if (_endDate != null) { _queryable = from q in _queryable where q.Year <= _endDate.Value.Year && q.Month <= _endDate.Value.Month select q; } } public override void FilterOnlyActive() { } public override void Sort() { _queryable = (from q in _queryable orderby q.Month descending orderby q.Year descending select q); } }
Active items
Fetching only active items is usually critical, when it applies.
Imagine that you want to be able to see all products in the admin area (so you can edit them, activate or deactivate them), but you only want your clients to see the active products. If you use the same query to load the products for both admin and client area, you have to tell your query when to include the inactive products and when not, otherwise your clients might have the unpleasant surprise of working with inactive products.
The decision of including the inactive items can be made at the UI / controller layer or at the application layer, depending on the requirements. The difference is that the application task which wraps the query will expect the parameter when executed by the controller, or make the decision itself without expecting a parameter.
In the SortingAndActiveItems action of the QueryController:
- we first load the list of active products by making the decision in the controller (the application task expects the parameter for including the inactive items or not)
var productList1 = _product2ListTask.Execute(false);
Product2ListTask is a wrapper for Product2Query, which also passes the decision from the controller to the query:
public class Product2ListTask: BaseListQueryTask<Product2> { private readonly Product2Query _product2Query; private bool _includeInactive; public Product2ListTask(INHUnitOfWorkProvider uowProvider, Product2Query product2Query) : base(uowProvider) { _product2Query = product2Query; } public IList<Product2> Execute(bool includeInactive) { _includeInactive = includeInactive; ExecuteInternal(); return Entity; } protected override IList<Product2> ExecuteQuery() { return _product2Query.Execute(UOW.Session, _includeInactive); } }
The query implements a method to bring only the active items by overriding the FilterOnlyActive method, and offers 2 Execute entry points (one which expects the decision from outside, and one which defaults to excluding the inactive items):
public class Product2Query: MultiCriteriaQuery<Product2> { public IList<Product2> Execute(ISession session, bool includeInactive) { return Load(session, includeInactive); } public IList<Product2> Execute(ISession session) { return Execute(session, false); } protected override void ApplyMainFilters(IListMultiCriteriaFetcher<Product2> criteria) { } protected override void FilterOnlyActive(IListMultiCriteriaFetcher<Product2> criteria) { criteria.Where(p => p.IsActive).Eq(true); } protected override void Sort(IListMultiCriteriaFetcher<Product2> criteria) { criteria.OrderAscBy(p => p.ProductName); } }
Here is how the entity looks like:
public class Product2 { public virtual int Id { get; set; } public virtual string ProductName { get; set; } public virtual bool IsActive { get; set; } }
- in the second example, we load the same list of active products by making the decision in the application layer (the application task always excludes inactive items when executing the query):
var productList2 = _clientProductListTask.Execute();
public class ClientProductListTask: BaseListQueryTask<Product2> { private readonly Product2Query _product2Query; public ClientProductListTask(INHUnitOfWorkProvider uowProvider, Product2Query product2Query) : base(uowProvider) { _product2Query = product2Query; } public IList<Product2> Execute() { ExecuteInternal(); return Entity; } protected override IList<Product2> ExecuteQuery() { return _product2Query.Execute(UOW.Session, false); } }
This also applies to situations when you have a certain state which is equivalent to the item being disabled (for example, a Cancelled state), and the same query needs to load the list including / excluding items in that state.
- in the third example, we load only orders which are not cancelled:
var ordersNotCancelled = _customerOrder4ListTask.Execute(false);
The task is simply a wrapper for the query:
public class CustomerOrder4ListTask: BaseListQueryTask<CustomerOrder4> { private readonly CustomerOrder4Query _customerOrder4Query; private bool _includeCancelled; public CustomerOrder4ListTask(INHUnitOfWorkProvider uowProvider, CustomerOrder4Query customerOrder4Query) : base(uowProvider) { _customerOrder4Query = customerOrder4Query; } public IList<CustomerOrder4> Execute(bool includeCancelled) { _includeCancelled = includeCancelled; ExecuteInternal(); return Entity; } protected override IList<CustomerOrder4> ExecuteQuery() { return _customerOrder4Query.Execute(UOW.Session, _includeCancelled); } }
The query implements a method to filter the Cancelled orders:
public class CustomerOrder4Query: MultiCriteriaQuery<CustomerOrder4> { public IList<CustomerOrder4> Execute(ISession session, bool includeCancelled) { return Load(session, includeCancelled); } protected override void ApplyMainFilters(IListMultiCriteriaFetcher<CustomerOrder4> criteria) { } protected override void FilterOnlyActive(IListMultiCriteriaFetcher<CustomerOrder4> criteria) { criteria.Where(p => p.State).NotEq(CustomerOrderState.Cancelled); } protected override void Sort(IListMultiCriteriaFetcher<CustomerOrder4> criteria) { criteria.OrderDescBy(p => p.OrderPrice); } }
And here are the entity and states enum:
public enum CustomerOrderState { InWork = 1, Sent = 2, Cancelled = 3, Accepted = 4} public class CustomerOrder4 { public virtual int Id { get; set; } public virtual decimal OrderPrice { get; set; } public virtual CustomerOrderState State { get; set; } }
About this entry
You’re currently reading “Active items and sorting,” an entry on The FwkLight blog
- Published:
- April 28, 2010 / 12:54 pm
- Category:
- Uncategorized
- Tags:
No comments yet
Jump to comment form | comment rss [?] | trackback uri [?]