-
Notifications
You must be signed in to change notification settings - Fork 55
Encapsulating Query Logic with the Query Object Pattern (Reusable Queries)
Long Le edited this page Sep 20, 2017
·
5 revisions
Examples done in LINQPad
public class OrderSalesQuery : QueryObject<Order>
{
public decimal Amount { get; set; }
public string Country { get; set; }
public DateTime FromDate { get; set; }
public DateTime ToDate { get; set; }
public override Expression<Func<Order, bool>> Query()
{
return (x =>
x.OrderDetails.Sum(y => y.UnitPrice) > Amount &&
x.OrderDate >= FromDate &&
x.OrderDate <= ToDate &&
x.ShipCountry == Country);
}
}
var orderRepository = new Repository<Order>(this);
var orders = orderRepository
.Query(new OrderSalesQuery(){
Amount = 100,
Country = "USA",
FromDate = DateTime.Parse("01/01/1996"),
ToDate = DateTime.Parse("12/31/1996" )
})
.Select();
public class CustomerLogisticsQuery : QueryObject<Customer>
{
public CustomerLogisticsQuery FromCountry(string country)
{
Add(x => x.Country == country);
return this;
}
public CustomerLogisticsQuery LivesInCity(string city)
{
Add(x => x.City == city);
return this;
}
}
public class CustomerSalesQuery : QueryObject<Customer>
{
public CustomerSalesQuery WithPurchasesMoreThan(decimal amount)
{
Add(x => x.Orders
.SelectMany(y => y.OrderDetails)
.Sum(z => z.UnitPrice * z.Quantity) > amount);
return this;
}
public CustomerSalesQuery WithQuantitiesMoreThan(decimal quantity)
{
Add(x => x.Orders
.SelectMany(y => y.OrderDetails)
.Sum(z => z.Quantity) > quantity);
return this;
}
}
Using the reusable CustomerLogisticsQuery and CustomerSalesQuery together by chaining them together.
var customerRepository = new Repository<Customer>(this);
var query1 = new CustomerLogisticsQuery()
.LivesInCity("London");
var query2 = new CustomerSalesQuery()
.WithPurchasesMoreThan(100)
.WithQuantitiesMoreThan(10);
customerRepository
.Query(query1.And(query2))
.Select()
.Dump();
The Official URF Team | Docs: goo.gl/6zh9zp | Subscribe to URF Updates: @lelong37 | Blog: blog.longle.io