Дизайн вопрос POCO объекты / DAL доступ - PullRequest
5 голосов
/ 09 ноября 2010

Я хотел бы реализовать типичную трехслойную архитектуру.Мой текущий подход выглядит следующим образом:

  • DAL - с EF 4.0 и репозиториями для каждой из моих сущностей.доступ через интерфейсы
  • Я думал об использовании объектов POCO.Мой первый вопрос будет где я должен положить эти файлы?В сборке, на которую ссылаются все другие проекты?
  • BLL - Как получить данные из DAL в BLL и, наконец, в GUI? Это хороший способ, если у меня будет целая кучаклассы менеджера там как CustomerManager в BLL.Эти классы будут обращаться к соответствующему хранилищу в BLL и затем передавать объекты в графический интерфейс

Или вы думаете, что лучше поместить хранилище в BLL и получить к ним доступ непосредственно из моего, скажем, buttoneventhandler?

Надеюсь, ты сможешь внести свет во тьму

Ответы [ 3 ]

6 голосов
/ 09 ноября 2010

У нас есть репо в DAL. BLL ссылается на репозитории через интерфейс - поэтому репозитории привязаны к DAL, но не связаны с BLL. Я не знаю ни одной причины, почему хранилища не могли быть непосредственно в BLL. У нас они есть в DAL, поскольку мы не вкладываем в них ЛЮБУЮ логику. Затем в BLL есть «Менеджеры», которые обертывают репозитории и обрабатывают логику, специфичную для сущности.

FWIW у нас на самом деле есть универсальный Repository(Of IEntity) и мы используем единство для создания экземпляра соответствующего репозитория по мере необходимости - он очень компактный и довольно элегантный. Все наши объекты POCO реализуют IEntity, который содержит Id, CreatedDate и т. Д., Которые являются общими для ВСЕХ наших объектов. Это дает некоторые другие преимущества, когда вам нужно обрабатывать сущности любого типа в общем - CreatedDate устанавливается репозиторием при вызове CreateInstance(), ModifiedDate устанавливается самим контекстом, когда он фиксирует сущность с состоянием Modified

Мы храним сущности в отдельном проекте - DAL должен иметь возможность ссылаться на них, как и BLL. Вы не хотите, чтобы они были в DAL, так как замена DAL вызывала бы проблемы. Вы не можете поместить их в BLL или получите круговую ссылку. Конфигурация для сущностей может находиться в DAL, так как она зависит от источника данных.

Мы стараемся придерживаться BLL, принимая примитивы и возвращая сущности. Будьте осторожны с хранением сущностей в пользовательском интерфейсе слишком долго, особенно в веб-приложении, поскольку у вас может быть другой контекст в DAL к тому времени, когда вы возвращаете сущность в BLL для обработки (т. Е. Между запросами, хранящимися в сеансе или подобном) может привести ко всем видам забавного присоединения / отсоединения сущностей от контекстов и лишит вас некоторых преимуществ, таких как отслеживание изменений.

Надеюсь, это поможет, но если вам нужны какие-либо разъяснения, дайте мне знать

3 голосов
/ 10 ноября 2010

Это наша установка:

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 .
  • Репозиторий - это набор универсальных классов, реализующих IRepository<T>, чтобы обеспечить базовое сохранение для базового хранилища.Найти, добавить, удалить и т. Д. Возвращает IQueryable. Ссылки POCO , Ссылка BLL .
  • Презентация является пользовательским интерфейсом. Ссылки POCO и BLL .

Конечный результат подобен стековому подходу, и поскольку в основном все осуществляется через интерфейсы (и реестры DI), гибкость огромна.

У нас есть Mock Repositories, которые вводятся в тестовые проекты через DI, и Entity Framework Repositories, которые вводятся в BLL через DI.

Пример потока из UI -> 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.

1 голос
/ 09 ноября 2010

Вы можете сделать это действительно просто, сохранив свои репозитории и POCO в одном проекте. По сути, это будет ваша модель предметной области. Ваши POCO являются публичными, как и ваши интерфейсы репозитория. Вы должны хранить свои конкретные репозитории внутри этого проекта.

Ваш BLL может быть классическим Фасадом или Сервисным Локатором. Этот проект будет обрабатывать ваши данные и применять любые соответствующие бизнес-правила, прежде чем передать их в пользовательский интерфейс. Это также будет отвечать за проверку данных, поступающих из пользовательского интерфейса, перед их отправкой в ​​DAL.

...