设计问题POCO对象/ DAL访问

时间:2010-11-09 17:14:40

标签: .net entity-framework repository-pattern poco

我想实现典型的三层架构。我目前的方法如下

  • DAL - 使用EF 4.0和我的每个实体的存储库。通过接口访问
  • 我在考虑使用POCO对象。我的第一个问题是我应该把它放在哪里 文件?在所有其他项目引用的程序集中?
  • BLL - 如何从DAL获取数据到BLL,最后到GUI 如果我在BLL中拥有像CustomerManager这样的一大堆管理器类,这是一个好方法。这些类将访问BLL中的相应存储库,然后将对象传递给GUI

或者您认为将存储库放在BLL中并直接从我说的buttoneventhandler中访问它们会更好吗?

希望你能为黑暗带来一些光明

3 个答案:

答案 0 :(得分:6)

我们在DAL中有回购。 BLL通过接口引用存储库 - 因此存储库与DAL绑定,但与BLL分离。我不知道为什么存储库不能直接在BLL中。我们在DAL中得到它们,因为我们没有在其中加入任何逻辑。然后,我们在BLL中有“管理器”,它包装存储库并处理特定于实体的逻辑。

FWIW我们实际上有一个通用Repository(Of IEntity)并使用unity来根据需要实例化相应的存储库 - 它非常紧凑且非常优雅。我们所有的POCO实体都实现了IEntity,其中包含IdCreatedDate等,这些都是我们所有实体共有的。当您需要一般处理任何类型的实体时,这会带来一些其他好处 - 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)
  • POCO是他们自己的集会。 不引用任何内容引用所有
  • BLL对存储库执行查询,应用业务规则和水合作用。 返回ICollection<T>T 引用存储库(通过IRepository<T>通用接口)和POCO
  • Repository是一组实现IRepository<T>的泛型类,用于为底层存储提供基本持久性。查找,添加,删除等返回IQueryable 引用POCO的由BLL引用
  • 演示文稿是UI。 引用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。