适合重构 - .NET 依赖注入

3

像大多数人一样,我一直在努力理解实体框架的某些细节。其中之一是上下文的生命周期。我正在使用存储库,并已决定上下文将在请求的整个过程中存在。因此,无论该存储库在Web层的哪个位置被使用,都需要从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个回答

2
这里的挑战在于,你所构建的并不是仓储库,而是仓储模式中的仓储库。仓储模式的一个目标是将数据访问层的实现与问题域分离。这通过一个行为像内存中的领域对象集合的仓储来实现,您可以执行正常的CRUD功能以及一些更具体的操作,例如GetByID(id)。

然后,仓储将实际的持久化层隐藏在应用程序中,从而允许您更改该层而不影响应用程序,例如您可以从存储数据的平面文件开始,然后转移到RDBMS。

通常,您会创建一个接口来描述您的仓储需要实现的方法,并使用该接口作为类型传递仓储实例。这就是抽象,该接口在所有可能的仓储具体实现中都是共同的,但您的应用程序对实际使用的内容是无知的(在某种程度上)。

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


谢谢Lazarus。我已经修改了示例存储库以提高清晰度(以防我的示例不完整)。我认为存储库模式被正确地用于数据访问,并且与解决方案中的Web域是分离的。你的第三段是我最感兴趣的——即如何使我的Web层与这些存储库交互,而无需编写一个愚蠢的帮助程序来为每个存储库类型注入上下文。 - Maleks
@Maleks:我使用一个DI容器(Castle Windsor)在存储库实例化时实例化上下文(当活动控制器需要它时,DI容器本身会实例化它)。您的存储库应该围绕Web应用程序与之交互的聚合根实体构建,这超出了此上下文的范围。具体实现的存储库与数据访问层之间的耦合度可以更紧密,这几乎是不可避免的,但应用程序到存储库的耦合度应该较低。 - Lazarus
我理解您的观点Lazerus。将尝试从Domain Oriented N-Layered .NET 4.0应用示例(DDD架构)示例项目(http://microsoftnlayerapp.codeplex.com/)中获取具体示例。 - Maleks
@Maleks:使用那个作为参考的想法非常棒! - Lazarus

0

你为什么没有使它类型安全? - jgauffin
@jgauffin,您能换一种方式提出您的问题吗? - smartcaveman
这看起来很有趣。我想看一下IRepository的示例以及您如何使用repo提供程序。 - Maleks

0

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


0

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

然后创建一个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

访问上下文。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接