2
\$\begingroup\$

I am working on a new MVC web application, so the project is in early stages. I have created 4 projects.

enter image description here

Let me explain what they do:

  1. Common --> contains all my DTOs, enums helpers, ViewModels etc.

  2. Web --> simple MVC application

  3. Business --> This contains providers which have an interface and implementation for dependency injection:

    enter image description here

  4. DAL --> Contains edmx file and DB Entities

DAL is similar to Business project. It has an IUsersDAL and then UsersDAL implementation.

enter image description here

Do I really need the DAL classes to access the database, or can I just access them from the Business class?

Just for an example I am adding a sample code from UsersProvider.cs:

This what my BusinessProvider is doing:

    private readonly IXPTSecurity _security;
    private readonly IUsersDAL _usersDAL;

    public UsersProvider(IXPTSecurity xptSecurity, IUsersDAL usersDAL)
    {
        _security = xptSecurity;
        _usersDAL = usersDAL;
    }

    public UserSessionModel AuthenticateUser(string userName, string password, ValidationContainer validationContainer)
    {
        var userInfo = _usersDAL.GetUserByUserNamePassword(userName, _security.Encrypt(password));

        if (userInfo == null)
        {
            validationContainer.AddMessage(MessageType.Error, "Login Failed. User name or password is incorrect.");
            return null;
        }

}

And then this is what is happening in the _usersDal.GetUserByUserNamePassword():

// So this is this is what UsersDAL is doing
    public User GetUserByUserNamePassword(string userName, string password)
    {
        return _managerEntities.Users.FirstOrDefault(s => s.sUserName == userName && s.sPassword == password);
    }

As you can see, all I am doing in my DAL classes is a simple LINQ type read from the database. If I do this in the Providers it saves me an extra layer.

It would be nice to get someone else opinion on this before I start coding.

By the way I need a separate Common and Business because this project requires another web application and another 3,4 Windows services, which will be later added using the same Business and Common. But I am not sure on the DAL.

\$\endgroup\$
3
\$\begingroup\$

I personally think that what you have done here by separating the layers is better than including this all in one layer....

  1. You're following the Single Responsibility Principle - Business Logic and data retrieval results in two different reasons for change and therefore I believe separating them in different classes is following this principle
  2. Your IUsersDAL can be stubbed in unit testing as this is injected into UsersProvider - you can separately test data access and business logic
  3. Reusing GetUserByUserNamePassword in numerous other business provider's means you don't have to write the same query again therefore you're promoting code reuse. Your UsersDAL is basically a repository pattern for the entity User as this will be used for storing the numerous LINQ queries associated with data retrieval for that entity. Maybe think object having repositories for aggregate root objects only.
  4. What if you changed your data retrieval for a User entity from a LINQ query to accessing them from a web service - you never know what might change in your application as it grows and you wouldn't want to be directly referencing web services in your business layer, accessing them through a Repository pattern would be a cleaner way of doing it.

I think developers sometimes doubt the extra layer due to the advantages of using an ORM and Linq as like you have done as you can create the data access retrieval within one query.

ORMs like Entity Framework are Unit Of Work and Repository patterns in themselves this is why having an extra layer to contain the query seems to be trivial, however I believe you're merely extending the repository as you're encapsulating data retrieval logic specific for an entity.

\$\endgroup\$
  • \$\begingroup\$ Cheers and thanks for the feedback, Just another question: I am passing my edmx model from DAL to Business, and then converting my DAL Model to a DTO, is this a good approach? \$\endgroup\$ – Dawood Awan Apr 18 '15 at 9:54
  • 1
    \$\begingroup\$ I think this is ok, you should look at creating an assembler to convert your DTOs to and from your domain model (edmx model) so this should be outside of your repository but callable from your UsersProvider. Your UsersProvider will then be a Service Layer which can then be either local or remote - this is part of your business layer. If you're thinking of converting all your domain objects accessible to your presentation layer as Local DTOs I would use the advice in the link \$\endgroup\$ – user978139 Apr 18 '15 at 14:50
2
\$\begingroup\$

My two cents on this architecture:

  1. A DAL whose purpose is store your queries is a good thing. Especially if your business logic often executes the same query, this really helps with the DRY principle. Entity framework can often generate inefficient queries (especially with the MySQL connector for some reason) and having each query in one place a great thing so that if you need to change it, you don't have to do so in a dozen places. I do occasionally expose the DbSet as an IQueryable from the DAL into the Business layer, but I've started to gravitate away from this since it's more trouble than its worth if your application is large (smaller ones I haven't had a hard time maintaining).

  2. Separate assemblies is good, but make your naming convenient. Instead of naming them Business, DAL, etc, name them with namespaced names. For example if my project's name was AwesomeService, my solution would be AwesomeService and I would name my projects AwesomeService.DAL, AwesomeService.Common, etc. This is very convenient because the namespaces nest together. Purely personal preference, however. I can say that every project I've done without this naming I've just felt icky during maintenance it since everything sits nearly in the global namespace and has lots of usings whose naming don't make sense. Microsoft's namespace naming conventions can help here as well, but I never go as far as they suggest with the company name and all.

  3. In my opinion, the whole point of this structure is for maintainability and ease of programming. If someone who doesn't know you were to come and read your code, could they quickly figure it out? Is the application structured well enough with good naming for you to know where to add another layer or replace a component if needed? Does the dependency chain between projects make your publish process difficult? So long as your structure is maintainable and flexible I would say it's good.

For your application:

I would isolate your DAL as much as possible and minimize the number of projects that depend on it directly. It is exceedingly annoying to need to republish 5 applications just because of one database change that only affects one of the projects, but will cause database errors if not updated in the others simply because they depend on the database and load a table. Obviously, this can't always be avoided, but I've started thinking carefully about ways to minimize this particular dependency. Whenever something depends on a database, that's another App.config that needs to be modified with passwords when one changes, another application that needs to be updated, and more time spent to test to make a sure a database change doesn't blow something up (although you may end up doing that anyway).

I don't let my entity framework entities escape the business logic into the layer that your controllers live in. I can't tell from your code example what your convention is, but I thought I might as well mention it. The navigation properties on entities wreak havoc with serializes as I'm sure you know. DTOs are your friend and anything that requires entity framework's persistence should be done entirely before your business logic methods return. Sometimes I've found that there are two layers in my business logic: the "outer" layer that communicate with the presentation in terms of DTOs or business objects and the "inner" layer that talks among itself and the database with entities and business objects.

Purely a matter of opinion, but you might want try to do your password encryption within your DAL. Every time you touch the user, you may need to hash a password. Don't invoke the hash method every time you call your GetUser... method. My reasoning for this opinion is for that if you have to change how hashing is done, that could be many dozens of places to need to change. Perhaps the DAL isn't the most logical place for it to go, but my impulse would be to put it right before you load the user from the database, inside your GetUser... method. Of course, this makes your DAL dependent on your IXPTSecurity interface, which may not work for you.

Summary

In answer to your question, if it were me, I would keep the DAL. The extra code is worth the ease of fixing queries.

\$\endgroup\$
  • \$\begingroup\$ Cheers and thanks for the feedback, Just another question: I am passing my edmx model from DAL to Business, and then converting my DAL Model to a DTO, is this a good approach? \$\endgroup\$ – Dawood Awan Apr 18 '15 at 9:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.