N-Tier Architecture with Service Layer, Business Layer, and Entity Framework

asp.net-mvc asp.net-mvc-2 asp.net-mvc-3 c# entity-framework

Question

Just wanted some feedback/help with the way I'm architecturing my application. My current solution structure looks something like this:

  • UI (Actual MVC application)
  • Core (only Controllers & ViewModels)
  • Services
  • BLL
  • Data (Entity framework DbContext, mapped to Domain objects)
  • Domain (Simple POCO objects)
  • Interfaces

Other stuff

  • Ninject to inject DbContext into Controller (per request)
  • AutoMapper to map Domain objects to ViewModel

All assemblies have a reference to the Interfaces project, which, as the name suggests, is nothing more than simple interfaces (i.e. IDbContext, IRepository, etc).

The Services project "ties" together everything else. It is the only assembly which has a direct reference to the Data access layer (Entity Framework).

I've provided some code below:

An example of a Controller looks like this:

namespace Core.Controllers
{
    public class HomeController : Controller
    {
        private IDbContext dbContext;

        public HomeController(IDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public ActionResult Users()
        {
            UserService userService = new UserService(dbContext);
            var users = userService.GetAllUsers();
            return View(Mapper.Map<IEnumerable<UserListViewModel>>(users));
        }
        ...

The UserService class:

namespace Services
{
    public class UserService
    {
        private readonly IDbContext dbContext;

        public UserService(IDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public IEnumerable<User> GetAllUsers()
        {
            IRepository<User> userRepository = new Repository<User>(dbContext);
            UserBLL userBLL = new UserBLL(userRepository);
            return userBLL.GetAllUsers();
        }
        ...

Finally, the business layer class:

namespace BLL
{
    public class UserBLL
    {
        private readonly IRepository<User> userRepository;

        public UserBLL(IRepository<User> userRepository)
        {
            this.userRepository = userRepository;
        }

        public IEnumerable<User> GetAllUsers()
        {
            return userRepository.Get();
        }
        ...

I'm looking for some feedback/ways to improve. I notice that for basic tasks, my service layer methods will be exactly the same as the business layer methods (i.e. "pass through" functions). What I'm hoping is that this abstraction will be helpful for more complex tasks which may require calls to multiple business layer methods. Would it just be better to include business logic in the service layer?

1
5
9/27/2012 4:57:30 PM

Accepted Answer

From a quick glance, I don't think your service and controller/core layer should have the db context injected into them in this manner. They don't actually directly depend on it and doing it in this manner causes some coupling that is not ideal. The core layer should have the user service injected and the user service and BLL should have the repository injected. The repository should have the dbcontext injected by your DI framework and not passed in as a dependency.

9
8/22/2012 8:14:17 PM

Popular Answer

Why are you using dependency injection when you are creating dependencies directly in the service?

public IEnumerable<User> GetAllUsers()
{
    IRepository<User> userRepository = new Repository<User>(dbContext);
    UserBLL userBLL = new UserBLL(userRepository);
    return userBLL.GetAllUsers();
}

Btw. why are you using so many layers when they actually do nothing? Your example code just shows that using context in controller directly would produce the same result without three wrapper useless layers. It may be just problem of your example but each layer should bring some added logic. If you just use it to call something on lower layer you are most probably overarchitecting your code. This is called onion architecture. That is also a reason why it is not a bad practice to add layer once you need it - not upfront.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow