成熟的重构 - .NET依赖注入

时间:2011-06-09 11:33:48

标签: c# .net entity-framework interface dependency-injection

与大多数人一样,我一直在处理实体框架的某些细节。其中之一就是上下文的生命周期。我正在使用存储库并且已经确定上下文将在请求的长度内存活。因此,无论使用哪个存储库,都需要从Web层注入上下文。

我已经编写了一些我确信可以重构的代码(事实上,绝对是!)。因此,基于上述概念,您将如何优化以下存储库帮助程序?

public class RepositoryHelper
{

    public static CountryRepository GetCountryRepository() {
        return new CountryRepository(HttpContext.Current.GetObjectContext());
    }

    public static CurrencyRepository GetCurrencyRepository()
    {
        return new CurrencyRepository(HttpContext.Current.GetObjectContext());
    }

    public static SettingRepository GetSettingRepository()
    {
        return new SettingRepository(HttpContext.Current.GetObjectContext());
    }

}

存储库非常简单,看起来像

public class CountryRepository
{

    private Context _context = null;
    public CountryRepository(Context context)
    {
        _context = context;
    }

    public Country GetById(int id) 
    {
        // Would return a country
    }

    public IEnumerable<Country> All()
    {
        // Would return a list of countries
    }

}

4 个答案:

答案 0 :(得分:2)

这里面临的挑战是,您构建的内容不是存储库模式意义上的存储库。存储库模式的目标是从问题域抽象数据访问层的实现。它通过一个存储库来完成,该存储库的行为类似于域对象的内存中集合,您可以使用它来执行常规CRUD函数,通常还有一些更具体的操作,即GetByID(id)。

然后,存储库会从应用程序中隐藏实际的持久层,允许您在不影响应用程序的情况下更改该层,即您可以先将数据存储在平面文件中,然后再移至RDBMS。

您通常会创建一个接口来描述存储库需要实现的方法,并使用该接口作为类型实际传递存储库实例。这是抽象,接口在您的存储库的所有可能的具体实现中是通用的,但是您的应用程序在某种程度上是无意识的,实际上正在使用它。

我建议退一步,再看看存储库模式,看看你是否需要它。确保您不仅仅是为了实现它而且不会不必要地增加应用程序的复杂性。一旦您确定了数据访问方法,就可以了解如何最好地利用您拥有的EF上下文。

答案 1 :(得分:0)

我认为您可以从C#/EF and the Repository Pattern: Where to put the ObjectContext in a solution with multiple repositories?的答案中使用Repository Provider类和Repository Factories中受益。

答案 2 :(得分:0)

对于DI,您可以使用Ninject并在绑定对象时使用InRequestScope方法。

答案 3 :(得分:0)

阅读我的答案here,了解如何建立通用会话管理器。

然后创建一个EntityFramework会话管理器(存储objectcontext)。

一些半完成的伪代码:

public static class EntityFrameworkSession
{
    [ThreadStatic] private static ObjectContext _current;

    public static AssignToSessionFactory()
    {
         SessionFactory.Created += OnCreateObjectContext;
         SessionFactory.Disposed += OnDisposeContext;
    }

    public static void OnDisposeContext(object source, SessionEventArgs e)
    {
         if (e.Saved)
           _myContext.SaveChanges();
    }
}

在您的存储库中使用:

EntityFrameworkSession.Current

访问上下文。