基于经典3层的项目:UI(在此问题中不重要),业务逻辑层和数据访问层。我有几个表:Customers
Products
Orders
Users
。设计应该是:
//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)
令我困惑的是,我发现DAL中的所有方法都是GetAllXXXX。我不得不承认这个设计工作正常。在DAL中,只有GetAll方法。在BLL中,只有组合操作(过滤/加入/选择)到GetAll方法。这很奇怪吗?什么是正确的方法?
答案 0 :(得分:2)
不,这并不奇怪,事实上这与我的表现非常相似。
只有我的差异:
IQueryable<T>
代替IEnumerable<T>
(以获得延迟执行)Repository<T>
):
IQueryable<T> Find()
void Add(T)
这样,我的存储库保持干净/简单。
所以你的BLL可以像这样实现:
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!
}
使BLL执行投影/工作/逻辑。存储库只处理T的持久性,不关心实际类型或任何业务逻辑。
无论如何,我就是这样做的。
答案 1 :(得分:1)
请考虑您的数据访问层可以提供以下服务:
GetSingleCustomer()
CalculateUpperManagementTuesdayReport()
我不会说它非常奇怪,但也许您的DAL不需要提供这些服务,因为您的应用程序不需要它们。
在BL中使用过滤器/加入/选择,我更喜欢IQueryable<t>
而不是IEnumerable<T>
。这意味着,在BL中调用Single()
,First()
,ToList()
,Count()
等之后,BL代码中的给定语句的执行才会发生。代码。
答案 2 :(得分:0)
我的问题是,如果合并当前的BLL和DAL,你会失去什么? - 它们似乎都在处理从持久数据(DB)到对象之间的差距。看起来像最简单的事情。 看待它的另一种方式是改变本地化?例如如果DAL层发生了变化,那么它是否会被隔离或是否会进入上层(这是不可取的)。
理想情况下,BLL应该封装域名规则/工作流程,即域知识。例如如果对某些客户的处理方式不同DAL用于将数据从持久状态转换为对象(或更高层消耗的数据结构),反之亦然。那是我今天的理解......