-
Notifications
You must be signed in to change notification settings - Fork 55
Adding Custom Queries to Repository
Long Le edited this page Sep 20, 2017
·
3 revisions
Add extension method for IRepository<TEntity>
or (if async) IRepostioryAsync<TEntity>
*Note: all things returned from Repository layer are of type TEntity
or IEnumerable<TEntity>
and not IQueryable<TEntity>
, addressing compartmentalization concern that all queries are actually happening in the Repository layer.
public static class CustomerRepository
{
public static decimal GetCustomerOrderTotalByYear(
this IRepository<Customer> repository,
string customerId, int year)
{
return repository
.Find(customerId)
.Orders.SelectMany(o => o.OrderDetails)
.Select(o => o.Quantity*o.UnitPrice)
.Sum();
}
// Custom query using IQueryable
public static IEnumerable<Customer> CustomersByCompany(
this IRepositoryAsync<Customer> repository,
string companyName)
{
return repository
.Queryable()
.Where(x => x.CompanyName.Contains(companyName))
.AsEnumerable();
}
public static IEnumerable<CustomerOrder> GetCustomerOrder(
this IRepository<Customer> repository,
string country)
{
var customers = repository.GetRepository<Customer>().Queryable();
var orders = repository.GetRepository<Order>().Queryable();
var query = from c in customers
join o in orders on new {a = c.CustomerID, b = c.Country}
equals new {a = o.CustomerID, b = country}
select new CustomerOrder
{
CustomerId = c.CustomerID,
ContactName = c.ContactName,
OrderId = o.OrderID,
OrderDate = o.OrderDate
};
return query.AsEnumerable();
}
}
/// <summary>
/// Add any custom business logic (methods) here
/// </summary>
public interface ICustomerService : IService<Customer>
{
decimal CustomerOrderTotalByYear(string customerId, int year);
IEnumerable<Customer> CustomersByCompany(string companyName);
IEnumerable<CustomerOrder> GetCustomerOrder(string country);
}
/// <summary>
/// All methods that are exposed from Repository in Service are overridable to add business logic,
/// business logic should be in the Service layer and not in repository for separation of concerns.
/// </summary>
public class CustomerService : Service<Customer>, ICustomerService
{
private readonly IRepositoryAsync<Customer> _repository;
public CustomerService(IRepositoryAsync<Customer> repository) : base(repository)
{
_repository = repository;
}
public decimal CustomerOrderTotalByYear(string customerId, int year)
{
// add business logic here
return _repository.GetCustomerOrderTotalByYear(customerId, year);
}
public IEnumerable<Customer> CustomersByCompany(string companyName)
{
// add business logic here
return _repository.CustomersByCompany(companyName);
}
public IEnumerable<CustomerOrder> GetCustomerOrder(string country)
{
// add business logic here
return _repository.GetCustomerOrder(country);
}
public override void Insert(Customer entity)
{
// e.g. add business logic here before inserting
base.Insert(entity);
}
public override void Delete(object id)
{
// e.g. add business logic here before deleting
base.Delete(id);
}
}
public class CustomerController : WebApi
{
private readonly ICustomerService _customerService;
public CustomerController(ICustomerService customerService)
{
_customerService = customerService;
}
public HttpResponseMessage CustomerOrderTotalByYear(string customerId, int year)
{
var total = _customerService.CustomerOrderTotalByYear(customerId, year);
return Request.CreateResponse(HttpStatusCode.OK, total);
}
}
The Official URF Team | Docs: goo.gl/6zh9zp | Subscribe to URF Updates: @lelong37 | Blog: blog.longle.io