C# 对多个存储库使用同一DbContext明智吗?

C# 对多个存储库使用同一DbContext明智吗?,c#,.net,entity-framework,repository-pattern,C#,.net,Entity Framework,Repository Pattern,深入了解实体框架和存储库,以实现更好的测试。想知道这是否明智吗 public interface IRepository { int SaveChanges(); void Dispose(); } using (MyContext context = new MyContext()) { TransactionRepository txns = new TransactionRepository(context); // TransactionRepository

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

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,以及一些为简洁起见我没有展示的查询方法


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

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

共享上下文还有其他很好的理由,其中一个原因是上下文必须跟踪实体的状态,如果您获得实体,则处理上下文,对实体进行一些修改,然后附加到新上下文。新上下文必须访问数据库,以便它能够了解实体的状态。同样,如果您正在处理实体发票及其所有发票项的图形,那么新上下文必须获取图形中的所有实体以确定其状态


现在,如果您使用的网页或服务没有或无法维护状态,那么UoW模式是一种隐含的,是一种普遍接受的良好实践。

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

共享上下文还有其他很好的理由,其中一个原因是上下文必须跟踪实体的状态,如果您获得实体,则处理上下文,对实体进行一些修改,然后附加到新上下文。新上下文必须访问数据库,以便它能够了解实体的状态。同样,如果您正在处理实体发票及其所有发票项的图形,那么新上下文必须获取图形中的所有实体以确定其状态


现在,如果您使用的网页或服务没有或无法保持状态,那么UoW模式有点含蓄,是一种普遍接受的良好做法。

+1 gorilla,提出了一些商品要点。我想补充以下想法

在web/mvc场景中,我使用了几十个存储库,并将上下文注入到这些存储库中。我使用存储库基类。 我还介绍了在构造函数中使用上下文的UoW类。 工作单元类包含对上下文支持的所有存储库的引用。我也使用有界上下文。以下是朱莉·勒曼关于这个主题的博客样本。

因此,使用多个上下文和多个存储库是非常有意义的。 您甚至可能有多个工作单元类,尽管UoW类的并发使用是另一个讨论

按要求添加示例代码: 此示例是从基础LuW类继承的几个LuW类之一。 将注入要使用的当前状态和DBContext。还是违约 存储库是来自核心项目的接口。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

我相信你已经了解了基本的想法……

+1大猩猩,提出了一些商品要点。我想补充以下想法

在web/mvc场景中,我使用了几十个存储库,并将上下文注入到这些存储库中。我使用存储库基类。 我还介绍了在构造函数中使用上下文的UoW类。 工作单元类包含对上下文支持的所有存储库的引用。我也使用有界上下文。以下是朱莉·勒曼关于这个主题的博客样本。

因此,使用多个上下文和多个存储库是非常有意义的。 您甚至可能有多个工作单元类,尽管UoW类的并发使用是另一个讨论

按要求添加示例代码: 此示例是从基础LuW类继承的几个LuW类之一。 将注入要使用的当前状态和DBContext。还是违约 存储库是来自核心项目的接口。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

我相信您已经了解了基本的想法……

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

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

我不明白为什么您会认为让多个类使用同一个实例有什么不对。你能解释你的担忧吗?取决于你的设计。例如,如果您遵循工作单元模式,那么您应该在相同的上下文中完成该单元所需的所有工作,在这种情况下,您将共享相同的上下文。主要是在一个存储库处理上下文的情况下,我不明白为什么你会认为让多个类使用同一个实例有什么不对。你能解释你的担忧吗?取决于你的设计。例如,如果您遵循工作单元模式,那么您应该在相同的上下文中完成该单元所需的所有工作,在这种情况下,您将共享相同的上下文。主要原因是,如果一个存储库处理了上下文,那么另一个存储库就不走运了。谢谢,我已经从直接使用EF进步,到存储库模式,然后我可能会进入工作单元。在这种情况下,我认为现在开始为存储库提供单独的上下文实例可能更干净。谢谢,我已经从直接EF使用发展到存储库模式,然后我可能会进入工作单元。在这种情况下,我认为现在开始为存储库提供单独的上下文实例可能更干净。我感谢您的反馈。我可以问一下,有几十个存储库,在一个控制器中注入最多的是什么?你有没有遇到过这样的情况,比如说,在一个控制器中需要5个以上的存储库?我保持存储库的小型化。通常每桌1个。LuW类有几十个存储库属性。请参阅示例代码的答案更新。我感谢您的反馈。我可以问一下,有几十个存储库,在一个控制器中注入最多的是什么?你有没有遇到过这样的情况,比如说,在一个控制器中需要5个以上的存储库?我保持存储库的小型化。通常每桌1个。LuW类有几十个存储库属性。有关示例代码,请参阅答案更新