-
Notifications
You must be signed in to change notification settings - Fork 19
Using Query Objects
geoffreysmith edited this page Aug 27, 2011
·
7 revisions
Inspiration: CQRS a la Greg Young
Query Objects and their contracts live in the Presentation Layer and are used to populate viewmodels. This accomplishes two objectives: getting rid of populating viewmodels in the Controllers as Controllers are meant to orchestrate, and keeping simply queries out of higher layers, such as Tasks.
public class ProductsListQuery : NHibernateQuery, IProductsListQuery
{
public IPagination<ProductViewModel> GetPagedList(int page, int size)
{
var query = Session.QueryOver<Product>().OrderBy(x => x.Name).Asc;
var count = query.ToRowCountQuery();
var totalCount = count.FutureValue<int>();
var firstResult = (page - 1) * size;
ProductViewModel viewModel = null;
ProductCategory categoryAlias = null;
var viewModels =
query.JoinAlias(x => x.Category, () => categoryAlias)
.SelectList(list => list
.Select(x => x.Id).WithAlias(() => viewModel.Id)
.Select(x => x.Name).WithAlias(() => viewModel.Name)
.Select(x => x.ProductNumber).WithAlias(() => viewModel.ProductNumber)
.Select(x => x.ListPrice).WithAlias(() => viewModel.ListPrice)
.Select(x => x.SellStartDate).WithAlias(() => viewModel.SellStartDate)
.Select(x => x.SellEndDate).WithAlias(() => viewModel.SellEndDate)
// Flattening the object graph
.Select(x => categoryAlias.Name).WithAlias(() => viewModel.CategoryName))
.TransformUsing(Transformers.AliasToBean(typeof(ProductViewModel)))
.Skip(firstResult)
.Take(size)
.Future<ProductViewModel>();
return new CustomPagination<ProductViewModel>(viewModels, page, size, totalCount.Value);
}
}
public interface IProductsListQuery
{
IPagination<ProductViewModel> GetPagedList(int page, int size);
}
public ActionResult Index(int? page)
{
var viewModel = new ProductsListViewModel
{
Products = this.productsListQuery.GetPagedList(page ?? 1, DefaultPageSize)
};
return View(viewModel);
}