LINQ query methods in the data access layer(DAL)
A project base on classic 3 layers: UI(not important in this question), business logic layer and data access layer. I have several tables: Customers
Products
Orders
Users
. The design is supposed to be:
//DAL methods
public IEnumerable<Customer> GetAllCustomers()
public IEnumerable<Product> GetAllProducts()
public IEnumerable<Order> GetAllOrders()
public IEnumerable<User> GetAllUsers()
//BLL methods
public IEnumerable<Order> GetOrders(long CustomerID)
public IEnumerable<Product> GetProducts(long CustomerID)
public IEnumerable<Product> GetProducts(long OrderID)
What confuses me is that I find that all methods in DAL are GetAllXXXX. And I have to admit that this design is working fine. In DAL there is nothing but GetAll methods. In BLL there is nothing but combined operati开发者_Go百科ons(filter/join/select) to GetAll methods. Is it weird? What's the correct way?
No, that's not weird, and in fact that is very similar to how i do it.
Only differences for me:
- I use
IQueryable<T>
instead ofIEnumerable<T>
(to get deferred exec) - I have a generic repository (
Repository<T>
):IQueryable<T> Find()
void Add(T)
- etc etc
This way, my repositories stay clean/simple.
So your BLL could be implemented like this:
public IEnumerable<Order> GetOrders(long CustomerID)
{
Repository<Order> orderRepository = new Repository<Order>(); // should use DI here, but i digress
return orderRepository
.Find() // no query executed...
.Where(o => o.CustomerID == CustomerID) // still nothing...
.ToList(); // query executed, with BL applied! cool!
}
Makes the BLL do the projection/work/logic. Repositories just handle persistence of T, doesn't care about the actual type, or any business logic.
That's how i do it anyway.
Consider that your data access layer could be providing services like:
- Create
- Update
- Delete
GetSingleCustomer()
CalculateUpperManagementTuesdayReport()
I wouldn't say it's terribly odd, but perhaps your DAL doesn't need to provide those services, as your application doesn't require them.
Having your filter/join/select in the BL, I'd prefer IQueryable<t>
instead of IEnumerable<T>
. This means that the execution of a given statement in the BL code doesn't happen until you call Single()
, First()
, ToList()
, Count()
, etc, etc within the BL code.
My question would be what would you lose if you merge the current BLL and the DAL? - they both seem to be dealing with bridging the gap from persisted data (DBs) to objects.. Seems like the simplest thing that would work. Another way of looking at it would be is change localized ? e.g. if there is a change in DAL layer, would that be isolated or would it ripple through into the upper layers (which is undesirable).
The BLL ideally should encapsulate the rules/workflows of your domain aka domain knowledge. e.g. if certain customers are treated differently. The DAL exists to transform your data from the persisted state into objects (or data structs to be consumed by higher layers) and vice versa. That's my understanding as of today...
精彩评论