在EF WCF服务中使用上下文和存储库

时间:2014-01-21 10:24:41

标签: c# wcf entity-framework testing mocking

我首先使用存储库模式在我的数据层中使用Entity Framework代码。我目前正在设计我的WCF Web服务以连接到数据层,我对如何链接数据层感到有些困惑。

在我的数据层测试项目中,我为每个测试创建一个新的DbContext类,将其包装在一个using块中,在其中创建存储库类,将上下文作为构造函数参数传递。然后,我可以在存储库中调用我的方法来获取数据。

这对于一个开始是正确的,然后我在WCF服务方法中也这样做吗?

例如我会

 public class UserService : IUserService
    {
        public bool CheckEmailAvailability(string email)
        {
            try
            {
                using (var context = new MyDbContext())
                {
                    var repository = new UserDataRepository(context);
                    var emailAvailable =
                        repository.GetItems().Count(
                            u => u.EmailAddress.Equals(email, StringComparison.InvariantCultureIgnoreCase)) == 0;

                    return emailAvailable;
                }
            }
        }
    }

或者我使用上下文/存储库概念错误了吗?

这也让我觉得在这里使用DI会很方便,所以我可以在WCF服务测试项目中模拟数据上下文/存储库对象。这通常是否已经完成,如果有的话,是否有人有关于此的示例或教程的任何链接?

1 个答案:

答案 0 :(得分:1)

首先,是的,最好是注入存储库,或者(如果您选择的DI框架无法解析它们)存储库的工厂。

此外,从服务中删除上下文的想法可能是个好主意。在我看来,存储库及其助手应该处理上下文,并在必要时共享组装实体所需的各种DB调用之间的上下文。然后,服务可以从存储库中请求实体,而不必担心它们是来自数据库还是其他数据存储的来源。

public class UserService: IUserService
{
    IUserRepository userRepository;

    ... // ctor to inject repository

    public bool CheckEmailAvailability(string email)
    {
        var emailAvailable = !userRepository.GetUserEmails().Any(u => u.EmailAddress.Equals(email, StringComparison.InvariantCultureIgnoreCase));

        return emailAvailable;                            
    }
}

public class UserRepository: IUserRepository
{
    ...

    public IEnumerable GetUserEmails()
    {
        // actually this context should be handled more centrally, included here for sake of illustration
        using (var context = new MyDbContext()) 
        {
            return repository.GetItems();
        }
    }
}

最后,关于WCF服务,我不确定最好的建议是什么。我见过代码,其中WCF服务是在业务逻辑中创建的,这很糟糕,但是旧版WPF代码库和有限DI的限制。更好的情况是可以将ChannelFactory或服务工厂注入服务层。您可以在Dependency Injection wcf上找到此答案。

和往常一样,如果您计划TDD代码,我肯定建议在应用程序的各个界面之间包含交叉点,以便更容易模拟。听起来你在那里有了正确的想法。