EF4存储库模式问题将存储库注入服务。似乎无法正确使用它

时间:2010-12-13 08:07:56

标签: entity-framework-4 moq repository-pattern

我发现很难测试EntityFramework 4.我使用数据库第一种方法使用它,现在来得太晚了,转移到poco.Needed提供非常快,没有时间像往常一样正常学习。

我已经使用工作单元实现了存储库模式,但我发现很难将存储库注入我的服务层,这样我就可以测试我的业务层服务的行为,验证等......而无需点击数据库。 但是我遇到了许多小问题。

  1. 为了将Repository注入服务(构造函数),调用层需要引用DAL(EF实体)。我不想要这个

  2. 如果我有许多存储库EG CustomerRepository,EmployeeRepository,我需要拥有与存储库一样多的构造函数,以便我可以注入存储库。

    3.不知道从哪里开始。我没有在网上找到任何使用EF4将存储库注入服务的示例。我看到的所有例子都是自己模拟存储库,这对我来说并不好。

  3. 我需要测试我的服务层/ BizLayer而不需要访问数据库。

    所有事情都是不可测试的,并且增加了很多依赖性和问题。

    我把Noddy的例子放在一起

    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 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();
            }
        }
    }
    

    以下TestMethod要求我在dal中添加一个参考点

        [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
    

    那里有任何建议或示例,说明如何做到这一点? 感谢

        }
    

1 个答案:

答案 0 :(得分:1)

简短的回答是 - 由于您没有使用POCO,所有图层都会引用您的DAL。

如果没有POCO,您可以使用代码生成,这意味着EF会在Model.edmx.designer.cs文件中创建模型类。

一个选项(尚未尝试过这个 - 在我的脑海中)是将EF实体手动投影到DTO中。

所以你的存储库可能会这样做:

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

OrderDTO类可以位于存储库引用的单独程序集中,也可以位于其他项目中。因此,其他项目将在DTO程序集中运行,并且不需要引用存储库。

但是在这里,你到处都是投入课程(基本上是做POCO,但是手动,还有更多的工作)从左到右复制属性 - 非常痛苦。

然而,这是一个选择。

老实说 - 不需要很长时间就可以转移到POCO。

有一个T4模板可以为您生成POCO - 您可以在几分钟内启动并运行。

既然您已经在使用依赖注入和存储库,那么您应该咬住子弹并更改为POCO,或保留对DAL的引用。