2011-06-09 79 views
3

与大多数人一样,我一直在关注Entity Framework的某些细节。其中一件事是上下文的生命周期。我正在使用一个存储库,并决定一个上下文将在请求的长度内生存。所以上下文需要从网络层注入,无论使用哪个版本库。重构的成熟 - .NET依赖注入

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

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 
    } 

} 

回答

2

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

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

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

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

+0

+1,很好的建议 – smartcaveman 2011-06-09 11:59:09

+0

谢谢拉撒路。为了清楚起见,我已经赞赏示例回购(如果我的示例不完整)。我认为存储库模式正在正确地用于数据访问,并与解决方案中的Web域分离。您的第三段是我最感兴趣的内容 - 即我的web层如何与这些存储库进行交互,而无需编写一个为每个存储库类型注入上下文的哑助手。 – Maleks 2011-06-09 12:38:34

+0

@Maleks:我使用DI容器(Castle Windsor)在存储库实例化时实例化上下文(当活动控制器需要时,它本身通过DI容器实例化)。您的存储库应该都基于您的Web应用程序与之交互的聚合根实体,超出此范围的范围才能深入了解。将存储库的具体实现与数据访问层更紧密地耦合是很好的,这实际上是不可避免的,但存储库耦合的应用应该是松散的。 – Lazarus 2011-06-10 10:46:53

0

我认为你会从使用存储库Provider类和库工厂就像在回答C#/EF and the Repository Pattern: Where to put the ObjectContext in a solution with multiple repositories?受益。

+0

你为什么不使它安全? – jgauffin 2011-06-09 11:39:41

+0

@jgauffin,你能改说你的问题吗 – smartcaveman 2011-06-09 11:48:19

+0

这看起来很有趣。我很想看到IRepository的一个例子,以及如何使用回购提供者。 – Maleks 2011-06-09 13:44:57

0

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

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 

访问上下文。