i would like to implement the typical three layer architecture. My current approach looks as follows
Or do you think it is better to put the repository in the BLL and access them directly from my say buttoneventhandler?
Hopefully you can bring some light into the darkness
We have the repos in the DAL. The BLL references the repositories via an interface - so the repositories are tied to the DAL but decoupled from the BLL. I don't know of any reason why the repositories couldn't be directly in the BLL. We've got them in the DAL as we don't put ANY logic in them. We then have "Managers" in the BLL which wrap the repositories and handle entity-specific logic.
FWIW we actually have a generic Repository(Of IEntity)
and use unity to instantiate the appropriate repository as required - it's very compact and quite elegant. All our POCO entities implement IEntity which contains Id
, CreatedDate
, etc. which are common to ALL our entities. This gives some other benefits when you need to handle any type of entity generically - CreatedDate
is set by the repository when CreateInstance()
is called, ModifiedDate
is set by the context itself when it commits an entity with a state of Modified
We keep entities in a separate project - The DAL needs to be able to reference them, as does the BLL. You don't want them in the DAL as swapping the DAL out would cause issues. You can't put them in the BLL or you get a circular reference. Configuration for the entities can live in the DAL as it's data source-specific.
We try to stick to the BLL taking in primitives and returning entities. Be careful about keeping entities in the UI for too long, especially in a web app as you may have a different context under the DAL by the time you return the entity to the BLL for processing (ie across requests stored in session or similar) this can result in all kinds of fun attaching/detaching entities from contexts and loses you some benefits like change tracking.
Hope that helps but if you want any clarification, let me know
This is our setup:
Company.Project.Domain.Model (POCOs)
Company.Project.Business.Services (BLL)
Company.Project.Data.Repositories (Repository)
Company.Project.Web (Presentation)
ICollection<T>
or T
. References Repositories (via IRepository<T>
generic interface) and POCOs.IRepository<T>
to provide basic persistence against underlying store. Find, Add, Remove, etc. Returns IQueryable
. References POCO's, Referenced by BLL.The end result is a like stack-like approach, and because basically everything is via interfaces (and DI registries), the flexibility is enormous.
We have Mock Repositories which get injected into the test projects via DI, and Entity Framework Repositories which get injected into the BLL via DI.
Example flow from 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>()); }
}
}
As you can see, i am a DI fanboy.
You can keep this really simple by keeping your repositories and POCOs in the same project. This would essentially be your Data Domain Model. Your POCOs are public and so are your repository interfaces. You should keep your concrete repositories internal to this project.
Your BLL could be a classic Facade or Service Locator. This project would massage your data and apply any relevant business rules before handing it over to the UI. This would also be responsible for validating data coming in from the UI before sending it over to the DAL.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With