3

Introduction

We require to build a n-tier application, as we would like to share our BL over multiple platforms and only write our DAL once. I've already done some research on this subject.

As can be read here in Davide Piras's post: MVC3 and Entity Framework each VS solution must at least have 4 layers. So far so good.

He also states that the DAL project is the only project which is allowed to even know that EF is being used.

Question 1:

I'm assuming, that the interfaces of the 'Interfaces' project are a 1 on 1 representation of my EF entities, am i correct on this? Also, these interfaces should be used as types between the different layers?

Question 2:

MSDN advices that the lifetime of a DbContext should be one context per request for WebApps, and one context per form in a WPF or WinForms project. So, how can i achieve this without adding 'System.Data.Entity' to my GUI layer?

Thnx in advance!

Community
  • 1
  • 1
Mark Rijsmus
  • 627
  • 5
  • 16
  • Thnx for the downvote, if i'm missing something, please care to comment.. I've put some energy and time to ask these questions. – Mark Rijsmus Feb 05 '15 at 07:17

2 Answers2

3

You need to use Unit of Work and Repository patterns with a Dependency Injection framework like StructureMap or Unity.

Basically, what you need to do is to create interfaces:

public interface IUnitOfWork
{
    void SaveChanges();
}

public interface IRepository<TItem>
{
    TItem GetByKey<TKey>();

    IQueryable<TItem> Query();
}

Now, in your DbContext class implement the interfaces above and somewhere in your Business Layer register the implementation of the interfaces:

public void RegisterDependencies(Container container)
{
    // Container is a Structure Map container.
    container.ForRequestedType<IUnitOfWork>()
        .CacheBy(InstanceScope.HttpContext)
        .TheDefaultConcreteType<DbContext>();    
}

See StructureMap Scoping Docs on how to configure the scope of an instance.

Now, with all that code in place, each of your Business Layer class that needs to perform some data operations would look like this:

public class SomeService
{
    public SomeService(IRepository<SomeItem> repository, IUnitOfWork unitOfWork)
    {
        this.repository = repository;
        this.unitOfWork = unitOfWork;
    }

    public void MarkItemCompleted(int itemId)
    {
        var item = repository.GetByKey(itemId);
        if(item != null)
        {
            item.Completed = true;
            unitOfWork.SaveChanges();
        }
    }
}

Now, hide the creation of services behind a factory:

public class ServiceFactory
{
    private readonly Container container;// = initialize the container

    public TService CreateService<TService>()
    {
        return container.GetInstance<TService>();
    }
}

And in your GUI layer call only methods of service classes created through ServiceFactory; if your GUI is an ASP.NET MVC project you don't need to create the ServiceFactory class - you can derive from DefaultControllerFactory and override GetControllerInstance method. See the answer here for an example.

Community
  • 1
  • 1
RePierre
  • 9,358
  • 2
  • 20
  • 37
  • Thnx for your clear response! It is very helpfull. I've already come across the Repositry and UOW pattern. I think the implementation of the Repo should be in the DAL, am i correct? Thnx again. – Mark Rijsmus Feb 05 '15 at 09:09
  • @MarkRijsmus, yes it should be in the Data Access. – RePierre Feb 05 '15 at 14:30
2

First of all DO NOT!!! share your DAL over multiple platform. Share your BL which uses DAL. As long as your BL represent solutions to your application requirements you do not need to expose your DAL and, please don't. Also exposing DAL has the disadvantage of exposing more vulnerabiilties to hackers and direct acces to DAL provides a btpass mechanism to your Business Logic, Controls and Validations in your BL.

Answer 1: Possibly but not need to. Thinking with SOA in mind I suggest to use DTOs. Either they are entities or more complex, composite classes of several and/or partial entities. If you use entities this gives you more flexibility to provide information via BL (you can send several portions of data at once by one method call) and hides youe entity (also DB structure) from third party users providing a better sense of security.

Answer 2: Again, thinking with SOA in mind, do not construct your BL/Service methods according to your User Interface. BL (as the name implies) provides data according to "how the work is done" not "how the work is done by the user on the screen". And if you try to manage your data from GUI you will also start to violate N-tier architecture. DO NOT!!! use any data spesific class and/or methods outside of DAL. This will be the true use of layering.

Regards.

user3021830
  • 2,784
  • 2
  • 22
  • 43
  • Thnx for your quick response! I'm sorry, what i meant to say was not sharing the DAL as in exposing it to other GUI's, but only write it once! My bad. – Mark Rijsmus Feb 05 '15 at 07:32
  • Yes, you've helped ;). I'll mark as answer in a couple of hours, i'm still waiting on more opinions, and i think people are more eager when a question is still unanswered. – Mark Rijsmus Feb 05 '15 at 07:50
  • No problem. I answer to help, not for reputation. Have a good day. – user3021830 Feb 05 '15 at 07:51
  • Nice, to you too sir! – Mark Rijsmus Feb 05 '15 at 07:55
  • Another question: do these DTO's, with its conversion from Entity, belong to the BLL? If yes, how to convert these, since you stated that 'BL (as the name implies) provides data according to "how the work is done" not "how the work is done by the user on the screen"'. Do you know any good examples of this matter? Thnx again for all the help! – Mark Rijsmus Feb 05 '15 at 12:06
  • 1
    Yes, it must be done in the BL. Any UI will only see your BL (as an API) and will communicate with this layer only. How to convert data depends on the language you are using, and/your development preferences. In my current project we are using ADO.NET only, so I am fetching the data from DB via Stored Procedures and return Interfaces from DAL. In BL I create Models (my UI is ASP.NET MVC only!!!) from interfaces and return it. But my preference would be using an ORM tool (such as Entity Framework as DAL) and writing LinQ queries to get the [this] (http://tinypic.com/r/2qnd3y1/8) structure. – user3021830 Feb 05 '15 at 12:25
  • Thnx! The latter one in c# is our practice. Is it best practice to create a method for each DTO type converted in the BLL, or should we create a generic method with a generict DTO-type constraint? In example: We have 2 views in which person data is displayed, one displays only 3 properties, and one 12 properties. We will create 2 DTO's for this: PersonSimple and PersonExtended. What is best to do now, create one generic method, or 2 methods with different names.. I hope you understand what i'm trying to say here. Regards. – Mark Rijsmus Feb 05 '15 at 12:42
  • Using interfaces is (almost) always best practice. And if you are behind a WCF Service Layer you will need Data Contracts, whih are intarfaces actually. But if using is service is not an option then interfaces become an option. Altough I prefer to use them it mauy be unnecessary or over-engineering to define them all. This is a decision that only the developer can make. – user3021830 Feb 05 '15 at 12:46