Posts tonen met het label autofac. Alle posts tonen
Posts tonen met het label autofac. Alle posts tonen

vrijdag 26 april 2013

IoC containers compared

There are quite a few different IoC containers for .Net. How does one decide which IoC container to use? There are performance comparisons made, but as even the slowest IoC container only takes 0.04 milliseconds to resolve a dependency, performance is not a good discriminator.
I've decided to do a feature comparisons of Autofac, Structuremap and Unity. The results can be read below.



Basic registration

Basic registration is easy in each of the frameworks.

Structuremap

ObjectFactory.Initialize(x =>

{
   x.For<ISomethingService>()
     .Use<SomethingService>();
}


Autofac

var builder = new ContainerBuilder();

builder.RegisterType<SomethingService>()
          .As<ISomethingService>();


Unity

IUnityContainer container = new UnityContainer();

container.RegisterType<ISomethingServiceSomethingService>();




Registration of a singleton

Setting lifetimescope options like "singleton" are easy in each of the frameworks.


Structuremap

ObjectFactory.Initialize(x =>

{
   x.For<IThatService>()
     .Singleton()
     .Use<ThatService>();

}



Autofac

var builder = new ContainerBuilder();

builder.RegisterType<ThatService>()
          .As<IThatService>()
          .SingleInstance();





Unity

IUnityContainer container = new UnityContainer();

container.RegisterType<IThatServiceThatService>(
                                                                new ContainerControlledLifetimeManager());

Personally I don't like the term ContainerControlledLifetimeManager. Structuremap and Autofac have more obvious terms (Singleton and SingleInstance).



Autoscanning assemblies

Some frameworks provide ways to automatically register all or specific classes from an assembly. This can really be helpfull if for example you want to register all repositories in your solution and you don't want to write every registration by hand.


Structuremap

ObjectFactory.Initialize(x =>

{
   x.Scan(a =>
             {
                a.Assembly("[AssemblyName]");
                a.WithDefaultConventions();
             });

}


Structuremap can autoscan assemblies, but you can't set any lifetimeoptions. If you want to do that, you have to write some custom code.


Autofac

var builder = new ContainerBuilder();


builder.RegisterAssemblyTypes(Assembly.Load("[AssemblyName]"))
                .Where(t => t.Name.EndsWith("Repository"))
                .AsImplementedInterfaces()
                .SingleInstance();


Autofac has the option to set lifetimeoptions. In the example above all repositories are registered as singletons (SingleInstance).

Unity

As far as I know, Unity doesn't provide a way to autoscan assemblies out of the box.
With Unity you can autoregister assemblies by using Unity Auto Registration. (Thanks to Björn Bailleul for letting me know).


Organizing registrations

In real-life you want to organize the registrations and not put everything in the global.asax.

Structuremap

public class UnitOfWorkRegistry : Registry
{
   public UnitOfWorkRegistry()
   {
      For<IUnitOfWork>().Singleton().Use<UnitOfWork>();
   }
}


ObjectFactory.Initialize(x =>

{
   x.AddRegistry<UnitOfWorkRegistry>();
}


Structuremap doesn't have a way to set any properties or pass constructor variables to the Registry.


Autofac

public class MyModule : Autofac.Module
{
   public bool RandomProperty { get; set; }

   protected override void Load(ContainerBuilder builder)
   {
      if (RandomProperty)
         builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().SingleInstance();
   }
}

builder.RegisterModule(new MyModule() { RandomProperty = true });


Unity

I didn't find a way to use modules or registries with Unity. If anyone knows how to do this, please let me know.


Documentation

Structuremap

The documentation of Structuremap is incomplete and outdated. For example the next text can be seen on the homepage of structuremap:

The current version 2.5.2 was released in January 2009, with a 2.6 release scheduled for no later than the end of January 2009.

At the moment of writing this blog the current version of Structuremap is 2.6.4.1 and updated on august 13, 2012. But there are more problematic errors, like the quickstart, which says you can use the next statement to register a type:

x.ForRequestedType<IValidator>()
 .TheDefaultIsConcreteType<Validator>();

And indeed you can, but the ForRequestedType and TheDefaultIsConcreteType are deprecated, so they shouldn't be on the quickstart anymore.

Another major gap in the documentation is that there's no information about ASP.Net MVC integration on the Structuremap homepage.



Autofac

I have no criticism on the Autofac documentation. It is frequently updated (last update was 59 minutes ago since writing this text), and it's extensive. The most important chapters are easy to be found on the wiki on the Autofac homepage.



Unity

I find it difficult to find the documentation on Unity. This is the path I had to follow for the online documentation:

1. Go to the Unity homepage (http://unity.codeplex.com/)
2. Click on the Documentation tab (http://unity.codeplex.com/documentation)
3. Click on the link to MSDN (http://msdn.microsoft.com/en-us/library/ff647202)
4. Click on the link to Unity 3 (http://msdn.microsoft.com/en-us/library/dn170416.aspx)
5. I've found only a link to a guide that can be downloaded, not what I was looking for.
6. Click on the link to Unity 2.0 (http://msdn.microsoft.com/en-us/library/ff663144.aspx)
7. Found the online info about configuring Unity (http://msdn.microsoft.com/en-us/library/ff660846(v=pandp.20).aspx)

The online documentation itself is extensive and tedious. I find it diffucult to navigate. For example the text about MVC integration is nowhere to be found.

The PDF that can be downloaded looks a lot more inviting than the online documentation.


Final verdict

Autofac has the most extensive featureset when it comes to registration of classes. The documentation is up to date and easy to read.

Structuremap does a pretty good job too, but lacks in autoscanning features. The documentation is outdated.

Unity doesn't provide a way to autoscan assemblies, which leads to writing a lot of code yourself if you need that. (corrected by remark of Björn Bailleul) I didn't find a way to organize the registrations like the way it can be done with Autofac or Structuremap. The documentation is hard to find and difficult to navigate.

donderdag 7 maart 2013

Building Windows Services using Autofac

In the previous article I've shown how you can build a Windows Service in .Net using Topshelf. In this article I will show how you can use Autofac in a Windows Service with Topshelf.

We ended the previous article with this little Windows Service:




Currently MyService is doing two things

1. looping till the Windows Service stops
2. Execute some work in the DoWork() method.

I don't think number two belongs in MyService. It violates the Single Responsibility Principle and as it's a private method, so we can't easily unit test it. The solution is to create a new class named Worker, and put all the work there:





Let's write the code for Worker:


public class Worker
{
   private Guid _workerId;

   public Worker()
   {
      _workerId = Guid.NewGuid();
   }

   public void Work()
   {
      Console.WriteLine("I am working. My id is {0}.", _workerId);

      Console.WriteLine("  Step 1");
     System.Threading.Thread.Sleep(1000);

     Console.WriteLine("  Step 2");
     System.Threading.Thread.Sleep(1000);

     Console.WriteLine("  Step 3");
     System.Threading.Thread.Sleep(1000);

     Console.WriteLine("  Step 4");
     System.Threading.Thread.Sleep(1000);

     Console.WriteLine("  Step 5");
     System.Threading.Thread.Sleep(1000);
   }
}


Now we can use Worker in MyService like this:


public class MyService
{
   readonly CancellationTokenSource _cancellationTokenSource;
   readonly CancellationToken _cancellationToken;
   readonly Task _task;

        public  MyService()
        {
            _cancellationTokenSource = new CancellationTokenSource();
            _cancellationToken = _cancellationTokenSource.Token;
            _task = new Task(DoWork, _cancellationToken);
        }

        private void DoWork()
        {
            while (!_cancellationTokenSource.IsCancellationRequested)
            {
                new Worker.Work();
            }
        }

        public void Start()
        {
            _task.Start();
        }

        public void Stop()
        {
            _cancellationTokenSource.Cancel();
            _task.Wait();
        }
    }


When we run the app we will get this output:


Configuration Result:
[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.
I am working. My id is 7b60edb6-1d44-4750-81de-09468daeaecb.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is 37c0e8bb-2f46-4dc7-8568-dac6b5f5e0eb.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is e1413c84-0c18-4682-b56a-7a94365d2b57.
  Step 1
  Step 2
   ...


Notice that the Worker gets a new id everytime.

At this moment the Worker doesn't have any dependencies. In the real world the Worker maybe needs Entity Framework, Log4Net, or has to call a WCF service. We can instanciate all these dependencies by hand in the while-loop, and but I like to use autofac to do this for me.


Autofac and Windows Services

Where are we going to initialize autofac? In the Main() method of Program:




Let's install the Autofac nuget package:




Now we can initialise Autofac in the Main() method of Program. First add a new using statement:

using Autofac;

Next add the following code to the top of the Main() method::


var builder = new Autofac.ContainerBuilder();
builder.RegisterType<MyService>();
var container = builder.Build();


We can now use the Autofac container to get an instance of MyService and let it run in Topshelf. This is the old code:


HostFactory.Run(hostConfigurator =>
{
   hostConfigurator.Service<MyService>(serviceConfigurator =>
   {
      serviceConfigurator.ConstructUsing(() => new MyService());
      serviceConfigurator.WhenStarted(myService => myService.Start());
      serviceConfigurator.WhenStopped(myService => myService.Stop());
   });

   hostConfigurator.RunAsLocalSystem();
   hostConfigurator.SetDescription("MyService using Topshelf");
   hostConfigurator.SetDisplayName("MyService");
   hostConfigurator.SetServiceName("MyService");
});


Replace the marked line with this line:

serviceConfigurator.ConstructUsing(() => container.Resolve<MyService>());

If we run the app again, we will get the same results as previously, but now MyService is instanciated by Autofac.



Inject the Worker

Now we are using Autofac the create an instance of MyService. So how about an instance of Worker?
This is a but trickier. Let me start by showing the way it won't work right. Then you'll get a clue about how to do it the right way.

Register the Worker with Autofac:


var builder = new Autofac.ContainerBuilder();
builder.RegisterType<MyService>();
builder.RegisterType<Worker>();
var container = builder.Build();


We can inject Worker in the constructor of MyService:


public class MyService
{
   readonly CancellationTokenSource _cancellationTokenSource;
   readonly CancellationToken _cancellationToken;
   readonly Task _task;
   readonly Worker _worker;

   public MyService(Worker worker)
   {
      _worker = worker;

      _cancellationTokenSource = new CancellationTokenSource();
      _cancellationToken = _cancellationTokenSource.Token;

      _task = new Task(DoWork, _cancellationToken);
   }
   . . .
}


And then use _worker in the DoWork() method:


private void DoWork()
{
   while (!_cancellationTokenSource.IsCancellationRequested)
   {
      _worker.Work();
   }
}



This is what we'll see when we run the app again:

Configuration Result:
[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.
I am working. My id is 08f6cc4a-e843-4d3d-a5c3-affeab56e0cf.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is 08f6cc4a-e843-4d3d-a5c3-affeab56e0cf.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5

I am working. My id is 08f6cc4a-e843-4d3d-a5c3-affeab56e0cf.
  Step 1


Notice that the Worker has the same id everytime. This is not the same as before, when we got a new id everytime.

The problem here is that Worker only gets injected once, and that instance is used everytime. But I want to get a new Worker everytime. How do we do that? We need to manage the lifetime of the components a bit better. (You can read more about that here and here)



LifetimeScope

We can tell Autofac that we want a new instance of Worker. We do this by creating a new Autofac LifetimeScope, and resolving a Worker from it. We have to change only a small bit of code for this to work. Let's start with the constructor of MyService:



public class MyService
{
   readonly CancellationTokenSource _cancellationTokenSource;

   readonly CancellationToken _cancellationToken;
   readonly Task _task;

   readonly ILifetimeScope _lifetimescope;

   public MyService(ILifetimeScope lifetimescope)
   {
      _lifetimescope = lifetimescope;

      _cancellationTokenSource = new CancellationTokenSource();
      _cancellationToken = _cancellationTokenSource.Token;

      _task = new Task(DoWork, _cancellationToken);
     }

   . . .
}

We can use the lifetimescope in the DoWork() method:


private void DoWork()
{
   while (!_cancellationTokenSource.IsCancellationRequested)
   {
      using(var workerScope = _lifetimescope.BeginLifetimeScope())
      {
         var worker = workerScope.Resolve<Worker>();
         worker.Work();
      }
   }
}

When we run the app now, we'll see that we get a new worker everytime again:

Configuration Result:

[Success] Name MyService
[Success] Description MyService using Topshelf
[Success] ServiceName MyService
Topshelf v3.1.106.0, .NET Framework v4.0.30319.18033
The MyService service is now running, press Control+C to exit.
I am working. My id is 4b7fb6b3-3222-4023-9452-790ff7feb49c.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is 02cb1bcd-64ca-417f-8d2b-f1afdeef75d6.
  Step 1
  Step 2
  Step 3
  Step 4
  Step 5
I am working. My id is 6da61ae3-8d50-4361-b0aa-4b77823c35b3.
  Step 1



Without ILifetimescope

We can make it even nicer by using a factory. Autofac can create factories out of the box for us.  You can read more about that here.

It works like this:

Change the constructor of MyService to accept an Autofac factory for Worker:




public class MyService
{
   readonly CancellationTokenSource _cancellationTokenSource;


   readonly CancellationToken _cancellationToken;
   readonly Task _task;


   readonly Func<Owned<Worker>> _workerFactory;

   public MyService(Func<Owned<Worker>> workerFactory)
   {
      _workerFactory = workerFactory;

      _cancellationTokenSource = new CancellationTokenSource();

      _cancellationToken = _cancellationTokenSource.Token;

      _task = new Task(DoWork, _cancellationToken);

   }
   . . .
}


We can use the _workerFactory in the DoWork() method:


private void DoWork()
{
   while (!_cancellationTokenSource.IsCancellationRequested)
   {
      using(var workerFactory = _workerFactory())
      {
         var worker = workerFactory.Value;
         worker.Work();
      }
   }
}





As you can see we never have to change anything in the registration with Autofac. We registered Worker once, and we can get an instance of Worker or a factory of Worker from Autofac if we want.
Also the lifetime and disposing is being managed by Autofac, which really makes it easy for us to focus in implementing the logic and not focus on the plumbing code.


maandag 4 maart 2013

Don't register dependencies in global.asax


When you use a Inversion of Control container to wsire up the dependencies, don't register the dependencies in the global.asax of your web project.

Something like this is what you will find in the Getting Started of most IoC containers;


public class MvcApplication : System.Web.HttpApplication
{
   protected void Application_Start()
   {
      ...

      var builder = new Autofac.ContainerBuilder();

      builder.RegisterControllers(typeof(MvcApplication).Assembly)
         .PropertiesAutowired();

      builder.RegisterType<SomeType>();
      builder.RegisterType<SomeotherType>();
      builder.RegisterType<AnotherType>();

      var container = builder.Build();

      DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
   }
}


The problem lies with the marked lines. When you add a WCF project you probably will use the same registrations. And then you add a Windows Service project, and you have to copy this code again. And soon you have three or even more places with the same duplicated code. As you application gets bigger, the number of registrations will  grow, and everytime you have to update the registrations at three or more places.


Solution

The solution is to use Modules:

Create a new project in your Visual Studio solution and add a class like this:


public class SomeDependenciesModule : Autofac.Module
{
   protected override void Load(ContainerBuilder builder)
   {
      builder.RegisterType<SomeType>();
      builder.RegisterType<SomeotherType>();
      builder.RegisterType<AnotherType>();
   }
}


(You can split the registrations in seperate modules if you like)

Now you can register the module like this:


public class MvcApplication : System.Web.HttpApplication
{
   protected void Application_Start()
   {
      ...

      var builder = new Autofac.ContainerBuilder();

      builder.RegisterControllers(typeof(MvcApplication).Assembly)
         .PropertiesAutowired();

      builder.RegisterModule(new SomeDependenciesModule());

      var container = builder.Build();

      DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
   }
}


Your WCF project and Windows Service will also only register the module. When you add a new dependency to the SomeDependenciesModule, you will only have to add it once, and not three or more times.



donderdag 28 februari 2013

Entity Framework in a multi layered application

In this blog I'll show you how you can use Entity Framework in an MVC.Net website, with a multi layered architecture. The main goals of the architecture to make unit testing and integration testing easy, and keep a clean sepeartion of concerns. To achieve this goal I will be using the concept of Dependency Injection (DI) and Autofac als IoC Container / DI framework.


1. Introduction

Let me start by introducing the layered architecture that I like to use for my web applications:


  • Database to store data.
  • Data Access layer which contains the linq queries that are executed against Entity Framework.
  • Domain Services layer, which holds the business logic and workflow logic.
  • MVC.Net website which talks only to the Domain Services layer.
  • WCF services which talk only to the Domain Services layer.


This isn't an uncommon approach. Main advantages are clean seperation of layers and easy reuse of domain logic by the MVC.Net website and the WCF services (and windows services if you like).


2. Setting up the solution

2.1 Data Access Layer

Let's start with creating the data access layer. In this example we have two entities:


public class Employee
{
   public virtual int Id { get; set; }
   public virtual string Name { getset; }
   public virtual double Salary { getset; }
   public virtual DateTime? JobEndDate { getset; }
   public virtual Organisation Organisation { getset; }
}

public class Organisation

{
   public virtual int Id { getset; }
   public virtual string Name { getset; }
   public virtual List<Employee> Employees { getset; }
}


Now we can add the entity framework context. I use Code First, so this is the context:


public class DatabaseContext : DbContext
{
   public DbSet<Employee> Employees { getset; }
   public DbSet<Organisation > Organisations { getset; }
}


Next we add two Data Access classess, which contain the linq queries on top of the Entity Framework context:


public class OrganisationDa
{
   public Organisation GetById(int id)
   {
      var ctx = new DatabaseContext ();
      return ctx.Organisations.Single(it => it.Id == id);
   }
}


public class EmployeeDa
{

   public void Add(Employee employee)
   {
      var 
ctx = new DatabaseContext ();
       
ctx.Employees.Add(employee);
       
ctx.SaveChanges();
   }
}


To summarize, this is what the DataAccess project looks like now:




We have a DatabaseContext, an Employee entity, an Employee DataAccess class, an Organisation entity and an Organisation DataAccess class.


2.2 Domain Services Layer

We can start to build the Domain Services Layer, and use the DataAccess classes:

public class EmployeeService
{
   
public void AddEmployee(string name, int organisationId)
   {
      var organisation = 
new OrganisationDa().GetById(organisationId);

      
var employee = new Employee();
      
employee.Name = "John";
      
employee.Organisation = organisation;

      
var employeeDa = new EmployeeDa();
      employeeDa.Add(
employee);
   }
}


As you can see we create a new employee and connect that to an existing organisation, Next we can use this service in an MVC.Net project.

2.3 MVC Layer

public class HomeController : Controller
{
   public ActionResult Index()
   {
      var employeeService = new EmployeeService();
      employeeService.AddEmployee("John", 1);

      return View();
   }
}


3. First problem - Multiple Entity Framework contexts

3.1 Introduction
If we would run the solution we created and the Index method of the HomeController is executed, we will get this exception from Entity Framework:

An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

This exception happens because the Organisation entity is referenced by the database context that was created in the GetById method of the Organisation class, and then added to the second database context along with the newly created employee in the Add method of the EmployeeDa class.



3.2 Solution

We can solve this problem by using only one DatabaseContext. We create this DatabaseContext in the AddEmployee method of the EmployeeService  and give it to each DataAccess class that is needed:

public class EmployeeService
{
   public void AddEmployee(string name, int organisationId)
   {
      var databasecontext = new DatabaseContext();
      var organisationDa = new OrganisationDa(databasecontext);
      
var employeeDa = new EmployeeDa(databasecontext);

      
var organisation = organisationDa.GetById(organisationId);

      
var employee = new Employee();
      employee.Name = "John";

      employee.Organisation = organisation;
         
      employeeDa.Add(e);
   }

}

We also have to change the DataAccess classe to accept the DatabaseContexta as constructor parameter:


public class OrganisationDa
{
   private DatabaseContext _databasecontext;

   public OrganisationDa(DatabaseContext databasecontext)
   {
      _databasecontext = databasecontext;
   }

   public Organisation GetById(int id)
   {
      return _databasecontext.Organisations.Single(it => it.Id == id);
   }
}



public class EmployeeDa
{
   private DatabaseContext _databasecontext;

   public EmployeeDa(DatabaseContext databasecontext)
   {
      _databasecontext databasecontext;
   }

   public Employee GetById(int id)
   {
      return _databasecontext.Employees.Single(it => it.Id == id);
   }

   public void Add(Employee employee)
   {
      _databasecontext.Employees.Add(employee);
      _databasecontext.SaveChanges();
    }
}

If we run the solution now, and execute the Index method of the HomeController, the new Employee will be added succesfully to the database.




4. Second problem - Not Unit Testable

4.1 Introduction
Our Domain Services can't be unit tested, but only integration tests can be written, because it uses the data access layer and the database.

Let's introduce a new method (GiveRaise) in the EmployeeService, that we went to test:

public class EmployeeService
{
   public void GiveRaise(int employeeId, double raise)
   {
      var databaseContext new DatabaseContext();
      var employeeDa = new EmployeeDa(databaseContext);
      var employee = employeeDa.GetById(employeeId);

      if (employee.JobEndDate.HasValue && employee.JobEndDate < DateTime.Now)

      {
         throw new Exception("This employee doesn't work here anymore");
      }

      employee.Salary = employee.Salary + raise;


      databaseContext.SaveChanges();
   }

}

We can write a test for the GiveRaise() method:


[TestMethod]
public void WorkingEmployeeCanGetRaise()
{
   var employeeService = new EmployeeService();

   // Act
   employeeService.GiveRaise(1, 100);

   // Assert
   var employee = employeeService.GetById(1);
   Assert.AreEqual(100, employee.Salary);
}

This test will only work if we have a database with an employee with Id 1 in it. It's not uncommon for a build service to not have a database. So this test can't be run. And even if there's a database, we don't want to test the database, we want to test the logic inside the Domain Service.


4.2 Solution one - In Memory Database

If we don't want to use a real database, we can use an in-memory database. We have to change the code of the EmployeeServicea bit:


public class EmployeeService
{
   DatabaseContext _databaseContext;

   public EmployeeService(DatabaseContext databaseContext)

   {
      _databaseContext = databaseContext;
   }


   public void GiveRaise(int employeeId, double raise)
   {
      var employeeDa = new EmployeeDa(_databaseContext);
      var employee = employeeDa.GetById(employeeId);

      if (employee.JobEndDate.HasValue && employee.JobEndDate < DateTime.Now)

      {
         throw new Exception("This employee doesn't work here anymore");
      }

      employee.Salary = employee.Salary + raise;


      _databaseContext.SaveChanges();

   }
}

Now we can inject a DatabaseContext into the EmployeeService  We can choose if we use a DatabaseContext that references a real database, or use for example Effort as In-memory database. Let's see how this works out in the Test:

[TestMethod]
public void WorkingEmployeeCanGetRaise()
{
   // Arrange
   DbConnection connection = Effort.DbConnectionFactory.CreateTransient();

   var databaseContext new DatabaseContext(connection);

   var workingEmployee = new Employee() Id = 1 };

   databaseContext.Employees.Add(workingEmployee);
   databaseContext.SaveChanges();

   var employeeService = new EmployeeService(context);

   // Act
   var employee = employeeService.GiveRaise(1, 100);

   // Assert
   Assert.AreEqual(100, employee.Salary);
}

4.3 Solution two - Mock objects

If we don't want to do anything with the DataAccess layer, we can use a fake DataAccess Layer, that doesn't need a database but just returns an employee. How does this work?

First we need to have a mocking framework, to create a mock of a the Employee DataAccess class. I like to use Moq. So I installed the nuget package of Moq into the Test project.

Moq, like most mocking libraries, can only create a mock from an interface, so we need to make an interface for EmployeeDa:

public interface IEmployeeDa
    {
        Employee GetById(int id);
        void Add(Employee employee);
    }


Let EmployeeDa implement this interface:


public class EmployeeDa : IEmployeeDa
{
   private DatabaseContext _databaseContext;

   public EmployeeDa(DatabaseContext databaseContext)
   {
      _databaseContext databaseContext;
   }

   public Employee GetById(int id)
   {
      return _databaseContext.Employees.Single(it => it.Id == id);
   }

   public void Add(Employee employee)
   {
      _databaseContext.Employees.Add(employee);
      _databaseContext.SaveChanges();
   }
}


Now we can create a mock of IEmployeeDa in the test:

var employeeDaMock = new Mock<IEmployeeDa>();

employeeDaMock
   .Setup<Employee>(it => it.GetById(1))
   .Returns(new Employee() { Id = 1, Salary = 0 });

var employeeDa = employeeDaMock.Object;

So how do we use this mocked EmployeeDa in the EmployeeService  We can inject it in the constructor, assign it to a private field, and use it in the methods like this:


public class EmployeeService
{
   DatabaseContext _databaseContext;
   IEmployeeDa _employeeDa;

   public EmployeeService(DatabaseContext databaseContext, IEmployeeDa employeeDa)
   {
      _databaseContext = databaseContext;
      _employeeDa = employeeDa;
   }

   public Employee GiveRaise(int employeeId, double raise)
   {
      var employee = _employeeDa.GetById(employeeId);

      if (employee.JobEndDate.HasValue && employee.JobEndDate < DateTime.Now)
      {
         throw new Exception("This employee doesn't work here anymore");
      }

      employee.Salary = employee.Salary + raise;

      _databaseContext.SaveChanges();

      return employee;
   }
}

To conclude this chapter, this is the complete test:

[TestMethod]
public void WorkingEmployeeCanGetRaise()
{
   // Arrange
   var context = new DatabaseContext();

   
var employeeDaMock = new Mock<IEmployeeDa>();
   employeeDaMock
      .Setup<Employee>(it => it.GetById(1))
      .Returns(new Employee() { Id = 1, Salary = 0 });

   
var employeeDa = employeeDaMock.Object;

   
var employeeService = new EmployeeService(context, employeeDa);

   // Act

   var employee = employeeService.GiveRaise(1, 100);

   // Assert

   Assert.AreEqual(100, employee.Salary);
}


5. Third problem - Unwanted EF queries in Domain Services

5.1 Introduction

Since the Domain Services have access to the Entity Framework context, it's possible to write queries to directly load entities from the database. This goes against the Single Responsibility Principle and Seperation of Concerns.

It's possible to do this in the 
EmployeeService:


public Employee GiveRaise(int employeeId, double raise)
{
   var employee = _databaseContext.Employees
                                .Include("Organisation")
                                .Single(it=>it.Id = employeeId);


   ...
}

What's wrong about this? The main problem is that once we start this way, soon a lot of methods in the Domain Services Layer will have queries on top of Entity Framework.

How can we prevent this?


5.2 Solution - Only expose Unit of Work

The solution is quite simple: the Domain Services Layer only needs the Unit of Work from Entity Framework, and not the Repositories. In other words, only the method SaveChanges() is needed, and not all the DbSets.

We can create a wrapper for the Entity Framework context like this:


public class UnitOfWork
{
   DatabaseContext _databaseContext;

   public UnitOfWork(DatabaseContext databaseContext)
   {
      _databaseContext = databaseContext;
   }

   public int SaveChanges()
   {
      return _databaseContext.SaveChanges();
   }
}

Use the UnitOfWork in the Domain Services Layer this way:

public class EmployeeService : IEmployeeService
{
   UnitOfWork _unitOfWork;
   IEmployeeDa _employeeDa;
   IOrganisationDa _organisationDa;

   public EmployeeService(UnitOfWork unitOfWork,

                                        IEmployeeDa employeeDa,
                                        IOrganisationDa organisationDa)
   {
      _unitOfWork = unitOfWork;
      _employeeDa = employeeDa;
      _organisationDa = organisationDa;
   }

   public Employee GiveRaise(int employeeId, double raise)

   {
      var employee = _employeeDa.GetById(employeeId);

      if (employee.JobEndDate.HasValue && employee.JobEndDate < DateTime.Now)

      {
         throw new Exception("This employee doesn't work here anymore");
      }

      employee.Salary = employee.Salary + raise;


      _unitOfWork.SaveChanges();


      return employee;

   }
}

5.3 Conclusion

The Entity Framework context is not exposed to the Domain Services Layer anymore, but only the Unit of Work is accessible. This means the we can no longer write direct queries onto Entity Framework from the Domain Services Layer, but the have the be written in the Data Access Layer. This leads to cleaner code and satisfies the Seperation of Concern better.



6 Fourth problem - Dirty Web Layer

6.1 Introduction

When we go back to the the MVC.Net project / Web Layer, we have to write this code to give an employee a raise:


public class HomeController : Controller
{
   public ActionResult Index()
   {
      var databaseContext = new DatabaseContext();
      var unitOfWork = new UnitOfWork(databaseContext);
      var employeeDa = new EmployeeDa(databaseContext);
      var organisationDa = new OrganisationDa(databaseContext);
      var employeeService = new EmployeeService(unitOfWork,
                                                                           employeeDa,
                                                                           organisationDa);

      employeeService.GiveRaise(1, 100);

      return View();
   }
}

Now we have problems two and three congregated in one project. We can't unit test the HomeController, we have access to the DatabaseContext and can write direct queries on top of Entity Framework.

Fortunately we can solve this. Unfortunately the solution to this problem takes a quite a bit of work. Let's start with part one of the solution.


6.2 Solution one - Move initialisation to the constructor

public class HomeController : Controller
{
   private EmployeeService _employeeService;


   public HomeController() : this(new DatabaseContext())
   {
   }

   public HomeController(DatabaseContext databaseContext)
   {
      var unitOfWork = new UnitOfWork(databaseContext);
      var employeeDa = new EmployeeDa(databaseContext);
      var organisationDa = new OrganisationDa(databaseContext);
      _employeeService = new EmployeeService(unitOfWork,
                                                                       employeeDa,
                                                                       organisationDa);
   }

   public ActionResult Index()
   {
      _employeeService.GiveRaise(1, 100);

      return View();
   }
}


There are two things nice about the code above:
1. The index() method doesn't have to worry about initialising the EmployeeService anymore;
2. If we want to test the Index() method, we can inject the DatabaseContext, so we can use for example an in memory database.

But there are also a few things that aren't so great:
1. We have access to the DatabaseContext and can write direct queries on top of Entity Framework;
2. We can't mock the EmployeeService;
3. If the EmployeeService needs another DataAccess class, we have to add it in the constructor of the controller too. The more controllers there are, the more work this is. This quickly gets pretty tedious.

Therefore, let's look at part two of the solution


6.3 Solution two - Use an IoC container

IoC containers are used to give control over instantiating object to an external framework. You set them up once, and the create and inject the object everytime it is needed. In the HomeController we need and EmployeeService, and we create it ourselves in the constructor. But we can use and IoC container for that too. My favorite one is Autofac.

After we installed the NugetPackage for Autofac (Autofac and Autofac ASP.NET MVC4 Integration) into the MVC project, we can setup autofac in the global.asax:

// needed usings:
// using Autofac;
// using Autofac.Integration.Mvc;


protected void Application_Start()
{
   ...

   var builder = new Autofac.ContainerBuilder();

   builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();

   // [Insert custom initialisation here]

   var container = builder.Build();

   DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

As Autofac is setup, we can start to register our Services and DataAccess classes. I like to do that in a new project, to keep the Web layer clean of all references that are not neccessary. I name this project AutofacInitialiser.

First we register the DataAcces classes


namespace Xample.AutofacInitialiser
{
   public class DataAccessModule : Autofac.Module
   {
      protected override void Load(ContainerBuilder builder)
      {
         builder.RegisterAssemblyTypes(Assembly.Load("Xmpl.DataAccess"))
                .Where(t => t.Name.EndsWith("Da"))
                .AsImplementedInterfaces()
               .InstancePerLifetimeScope();
      }
   }
}

And register this module in the global.asax:


protected void Application_Start()
{
   ...


   var builder = new Autofac.ContainerBuilder();

   builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();

   builder.RegisterModule(new DataAccessModule());

   var container = builder.Build();

   DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

What did we just do? We've created a Module that scans the DataAccess Layer and registers every class the ends with Da in Autofac. This means that if we write OrderDa, or ProductDa, or whateverDa, they are registered automatically with autofac, without writing any special code.

We can write a Module for the Domain Services too:

public class DomainServicesModule : Autofac.Module
{
   protected override void Load(ContainerBuilder builder)
   {
      builder.RegisterAssemblyTypes(Assembly.Load("Xmpl.DomainServices"))
                .Where(t => t.Name.EndsWith("Service"))
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope();
   }
}

and register it in the global.asax:

protected void Application_Start()
{
   ...


   var builder = new Autofac.ContainerBuilder();

   builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();


   builder.RegisterModule(new DataAccessModule());

   builder.RegisterModule(new DomainServicesModule());

   var container = builder.Build();

   DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

}

And finally we write a module for all Entity Framework related classes:


public class EntityFrameworkModule : Autofac.Module
{
   protected override void Load(ContainerBuilder builder)
   {
      builder.RegisterModule(new DataAccessModule());

      builder.RegisterType<DatabaseContext>()
                .AsSelf()
                .InstancePerLifetimeScope();

       builder.RegisterType<UnitOfWork>()
                .AsSelf()
                .InstancePerLifetimeScope();
   }
}

and register it in the global.asax:

protected void Application_Start()
{
   ...


   var builder = new Autofac.ContainerBuilder();

   builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();


   builder.RegisterModule(
new DataAccessModule());
   builder.RegisterModule(new DomainServiceModule());
   builder.RegisterModule(new EntityFrameworkModule());

   var container = builder.Build();


   DependencyResolver.SetResolver(
new AutofacDependencyResolver(container));
}


Now we can inject the EmployeeService into the HomeController like this:

public class HomeController : Controller
{
   private IEmployeeService _employeeService;

   public HomeController(IEmployeeService employeeService)
   {
      _employeeService = employeeService;
   }

   ...
}

6.4 Conclusion

As you can see, there's no need to instansiate the Data Access classes, or anything related to Entity Framework anymore. This means we can even remove the reference to Entity Framework from the Web Layer. We have achieved a clean solution which solves the problems we had before:

1. We have no access to the DatabaseContext from the Web Layer, and can't write direct queries on top of Entity Framework;
2. We can mock the EmployeeService;
3. If the EmployeeService needs another DataAccess class, we don't have to add it in the constructor of the controller anymore, and don't have to add anything to the Autofac inisialisation code.




7 Final thoughts

In this blog I wrote how to create a Visual Studio solution with three layers (Data Access, Domain Services and Web) which are clearly seperated from each other, and are easy to test. I've achieved this by wrapping the Entity Framework context and by using Autofac as IoC container.