【问题标题】:Is it wise to use same DbContext with multiple repositories?将相同的 DbContext 与多个存储库一起使用是否明智?
【发布时间】:2013-01-31 00:04:58
【问题描述】:

深入了解实体框架和存储库,以实现更好的测试。想知道这是否明智?

public interface IRepository
{
    int SaveChanges();

    void Dispose();
}

using (MyContext context = new MyContext())
{
    TransactionRepository txns = new TransactionRepository(context); // TransactionRepository implement IRepository
    MappingRepository maps = new MappingRepository(context); // MappingRepositoryimplement IRepository

    SomeCommand command = new SomeCommand(txns, maps);
    command.Execute();
}

每个存储库在逻辑上都是不同的,因此理论上可能位于不同的数据源中。目前,他们使用相同的数据库。每个存储库类都实现了 IRepository,尤其是 SaveChanges() 以及一些我为了简洁而没有显示的查询方法。

利用多个存储库的好做法是什么?

【问题讨论】:

  • 我不明白为什么你会认为让多个类使用同一个实例有什么问题。你能解释一下你的担心吗?
  • 取决于您的设计。例如,如果您遵循工作单元模式,那么您应该在同一上下文中完成该单元所需的所有“工作”,在这种情况下,您将共享相同的上下文。
  • 主要是如果一个存储库处理了上下文,那么另一个存储库就不走运了。

标签: c# .net entity-framework repository-pattern


【解决方案1】:

+1大猩猩,赚了点货。我将添加以下想法。

在 web/mvc 场景中,我使用了几十个存储库并将上下文注入这些存储库。我使用存储库基类。 我还在构造函数中使用上下文的 UoW 类。 工作单元类包含对上下文所有受支持存储库的引用。我也使用有界上下文。这是 Julie Lerman 关于这个主题的示例博客。 http://www.goodreads.com/author/show/1892325.Julia_Lerman/blog

所以是的,使用多个上下文和使用多个存储库非常有意义。 您甚至可以有多个工作单元类,但同时使用 UoW 类是另一个讨论。

按要求添加示例代码: 此示例是从基本 LuW 类继承的几个 LuW 类之一。 当前状态和要使用的 DBContext 被注入。 (或默认) 存储库是来自 CORE 项目的接口。 LuW 类在 DAL 项目中。

基本的 LuW 类似于....

public interface ILuw : ILuwEvent, IDisposable
  {

   IBosCurrentState CurrentState{ get; set; }
   OperationStatus Commit();

   }

Luw 类本身。

namespace XYZ.DAL
{
public class LuwBosMaster : Luw, ILuwBosMaster
{
    public LuwBosMaster(DbContext context, IBosCurrentState currentState)  
    {
       base.Initialise(context,currentState); 
    }
    public LuwBosMaster()
    {

        base.Initialise(GetDefaultContext(), BosGlobal.BGA.IBosCurrentState);
    }
    public static DbContextBosMaster GetDefaultContext()
    {
     return new DbContextBosMaster("BosMaster");
    }

    //MasterUser with own Repository Class
    private IRepositoryMasterUser _repositoryMasterUser;
    public  IRepositoryMasterUser RepMasterUser
    { get { return _repositoryMasterUser ?? (_repositoryMasterUser = new RepositoryMasterUser(Context, CurrentState)); } }

    //20 other repositories declared adn available within this Luw
    // Some repositories might address several tables other single tables only.
    //  The repositories are based on a base class that common generic behavior for each MODEL object

我确定你明白了基本的想法......

【讨论】:

  • 感谢您的反馈。我能问你,有几十个存储库,你在一个控制器中注入的最多是什么?你有没有遇到过在单个控制器中需要超过 5 个存储库的情况?
  • 我的存储库很小。通常每桌 1 个。 LuW 类具有数十个存储库属性。查看示例代码的答案更新
【解决方案2】:

这实际上归结为您的设计决策。如果您遵循工作单元模式,那么每个存储库可能都有自己的上下文;主要是因为根据 UoW,每个存储库调用都应该创建它的上下文,完成它的工作,然后处置它的上下文。

不过,共享上下文还有其他充分的理由,其中之一(恕我直言)是上下文必须跟踪实体的状态,如果你得到一个实体,处置上下文,对实体,然后附加到一个新的上下文这个新的上下文必须去访问数据库,以便它可以找出实体的状态。同样,如果您正在使用实体图(发票及其所有 InvoiceItems),则新上下文必须获取图中的所有实体以确定它们的状态。

现在,如果您使用的网页或服务不存在或无法维持状态,那么 UoW 模式在某种程度上是隐含的,它是一种普遍接受的“良好做法”。

【讨论】:

  • 谢谢,我一直在从直接使用 EF 到存储库模式,然后我可能会进入工作单元。在这种情况下,我认为现在开始为存储库提供单独的上下文实例可能更清洁。
【解决方案3】:

最重要的事情忘记了:数据库连接不是在多个DbContext 实例之间共享的。这意味着如果您希望多个存储库位于同一事务中,则必须使用分布式事务。与本地事务相比,这是一个很大的性能下降。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 2011-03-17
    • 2018-08-16
    相关资源
    最近更新 更多