Search code examples
entity-framework-4moqrepository-pattern

EF4 Repository Pattern problems injecting repository into service .Cannot seem to get it right


I am finding difficult to test EntityFramework 4 .I am using it using the database first approach,too late now to move to poco.Needed to deliver pretty quickly,no time to learn properly as usual.

I have implemented the repository pattern with unit of work but I am finding difficult to inject a repository into my Service layer so that I can test the behaviour of my business layer service ,validation etc... without hitting the db. but I am incurring in many little problems.

  1. In order to inject the Repository into the service(constructor) the calling layer need to have a reference to the DAL (EF Entities) . I dont want this

  2. If i have many repositories EG CustomerRepository ,EmployeeRepository than I need to have as many constructors as repositories so that I can inject the repository.

    3.Not sure where to go from here. I have not found any example on the net where they inject the repository into the service using EF4. All the examples I have seen they mock the repository on it's own,which is not good to me.

I need to test my service layer/BizLayer without hitting the database.

The all thing is just not testable and adds so many dependencies and problems.

Noddy example I have put together

public class DepartmentServiceLibrary
{
    private readonly IDepartmentRepository _departmentRepository;

    public DepartmentServiceLibrary(IDepartmentRepository  departmentRepository)
    {
        _departmentRepository = departmentRepository;
    }

    public List<DepartmentDto> GetDepartments()
    {
        return DeparmentBiz.GetDepartments();
    }

    private DeparmentBL _departmentBiz;
    private DeparmentBL DeparmentBiz
    {
        get
        {
            return _departmentBiz ?? new DeparmentBL(_departmentRepository);
        }
    }
}

//internal class

internal class DeparmentBL
{
    private readonly IDepartmentRepository _departmentRepository;

    public DeparmentBL(IDepartmentRepository departmentRepository)
    {
        _departmentRepository = departmentRepository;
    }

    public List<DepartmentDto> GetDepartments()
    {
        using (var ctx = new AdventureWorksContext())
        {
            var uow = new UnitOfWork(ctx);
            _departmentRepository.UnitOfWork = uow;
            var query = _departmentRepository.GetAll();

            return query.Select(dpt => new DepartmentDto
                                           {
                                               DepartmentId = dpt.DepartmentID,
                                               Name = dpt.Name,
                                               GroupName = dpt.GroupName
                                           }).ToList();
        }
    }
}

The following TestMethod requires me to add a ref to the dal which defeats the point

    [TestMethod]
    public void Should_be_able_to_call_get_departments()
    {
        var mock = new Mock<IDepartmentRepository>();
        var expectedResult = new List<Department>();  //Dependency to DAL as Department is a EF Entity generated by EF.

        mock.Setup(x => x.GetAll()).Returns(expectedResult);
        var companyService = new MyCompanyBL(mock.Object);  //InternalVisibileTO
        var departments = companyService.GetAll();
        //assert removed for brevity

Any suggestions or examples out there that shows how to do it? thanks

    }

Solution

  • The short answer is - since you're not using POCOs, all your layers will have a reference to your DAL.

    Without POCOs, you use code generation, which means EF creates the model classes in the Model.edmx.designer.cs file.

    An option (haven't tried this - off the top of my head) is to manually project the EF entities into DTOs.

    So your Repository might do this:

    public List<OrderDTO> GetOrdersForCustomer(int customerId)
    {
       return _ctx.Orders
            .Where(x => x.CustomerId == customerId)
            .ToList()
            .Select(x => new OrderDTO { // left to right copy });
    }
    

    The OrderDTO class could be in a separate assembly, which the repository references, as well as your other projects. So the other projects would work off the DTO assembly, and wouldn't require a reference to the Repository.

    But here you're projecting into classes everywhere (basically doing POCO, but manually, and with more work) left to right copying of properties - very painful.

    However, that is an option.

    Honestly - it does not take long to move to POCOs.

    There is a T4 template which will generate the POCOs for you - you could be up and running in a matter of minutes.

    And since you're already using dependency injection and repository, you should either bite the bullet and change to POCOs, or keep the reference to the DAL.