我想实现典型的三层架构。我目前的方法如下
或者您认为将存储库放在BLL中并直接从我说的buttoneventhandler中访问它们会更好吗?
希望你能为黑暗带来一些光明
答案 0 :(得分:6)
我们在DAL中有回购。 BLL通过接口引用存储库 - 因此存储库与DAL绑定,但与BLL分离。我不知道为什么存储库不能直接在BLL中。我们在DAL中得到它们,因为我们没有在其中加入任何逻辑。然后,我们在BLL中有“管理器”,它包装存储库并处理特定于实体的逻辑。
FWIW我们实际上有一个通用Repository(Of IEntity)
并使用unity来根据需要实例化相应的存储库 - 它非常紧凑且非常优雅。我们所有的POCO实体都实现了IEntity,其中包含Id
,CreatedDate
等,这些都是我们所有实体共有的。当您需要一般处理任何类型的实体时,这会带来一些其他好处 - CreatedDate
在调用CreateInstance()
时由存储库设置,ModifiedDate
由上下文本身在提交时设置状态为Modified
我们将实体保留在一个单独的项目中--DAL需要能够引用它们,就像BLL一样。你不希望它们在DAL中,因为交换DAL会导致问题。你不能把它们放在BLL中,或者你得到一个循环引用。实体的配置可以存在于DAL中,因为它是特定于数据源的。
我们试图坚持BLL接受基元和返回实体。小心将实体保留在UI中太长时间,尤其是在Web应用程序中,因为当您将实体返回到BLL进行处理时(即,在会话中存储的请求或类似内容),您可能在DAL下具有不同的上下文可以导致从上下文中附加/分离实体的各种乐趣,并失去一些好处,如更改跟踪。
希望有所帮助,但如果您想要任何澄清,请告诉我
答案 1 :(得分:3)
这是我们的设置:
Company.Project.Domain.Model (POCOs)
Company.Project.Business.Services (BLL)
Company.Project.Data.Repositories (Repository)
Company.Project.Web (Presentation)
ICollection<T>
或T
。 引用存储库(通过IRepository<T>
通用接口)和POCO 。IRepository<T>
的泛型类,用于为底层存储提供基本持久性。查找,添加,删除等返回IQueryable
。 引用POCO的,由BLL引用。最终结果是类似堆栈的方法,因为基本上所有东西都是通过接口(和DI注册表),灵活性是巨大的。
我们有通过DI注入测试项目的模拟存储库,以及通过DI注入BLL的实体框架存储库。
来自UI的示例流程 - &gt; DB:
// "Company.Project.Web.ProductsController.cs"
public class ProductsController : BaseController
{
private IProductService _productService;
public ProductsController(IProductService productService)
{
this._productService = productService; // DI makes me happy :)
}
public ActionResult GetOrdersForProduct(Product product)
{
var orders = _productService.GetOrders(product);
return View(orders);
}
}
// "Company.Project.Business.Services.ProductService.cs"
public class ProductService : IProductService
{
private IRepository<Product> _productRepository;
public ProductService (IRepository<Product> productRepository)
{
this._productRepository = productRepository; // DI makes me happy :)
}
public ICollection<Orders> GetOrdersForProduct(Product product)
{
return _productRepository
.Find()
.ForProduct(product) // IQueryable<Product> pipe/extension filter
.ToList();
}
}
// "Company.Project.Data.Repositories.GenericRepository.cs
public class GenericRepository<T> : IRepository<T> where T : class
{
private IObjectSet<T> _objectSet;
public GenericRepository(IUnitOfWork unitOfWork)
{
CurrentContext = unitOfWork as SqlServerUnitOfWork;
}
public IQueryable<T> Find()
{
return CurrentContext.GetEntitySet<T>();
}
protected SqlServerUnitOfWork CurrentContext { get; private set; }
protected IObjectSet<T> CurrentEntitySet
{
// some plularization smarts in "SqlServerUnitofWork.cs", to dynamically pull
// back entity set based on T.
get { return _objectSet ?? (_objectSet = CurrentContext.GetEntitySet<T>()); }
}
}
如您所见,我是DI粉丝。
答案 2 :(得分:1)
通过将您的存储库和POCO保存在同一个项目中,您可以保持这一点。这基本上就是您的Data Domain Model。您的POCO是公共的,您的存储库接口也是公共的。您应该将具体存储库保留在此项目的内部。
您的BLL可能是经典的Facade或服务定位器。该项目将按摩您的数据并应用任何相关的业务规则,然后再将其交给UI。这也将负责验证来自UI的数据,然后再将其发送到DAL。