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.
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
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 Depa开发者_开发问答rtmentDto
{
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
}
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.
Something similar in terms of code can be seen here in GitHub and detail explanation can be found in TechNet
精彩评论