C# 如何在没有显式引用的情况下访问OpenDBContext?

C# 如何在没有显式引用的情况下访问OpenDBContext?,c#,asp.net,asp.net-mvc,entity-framework,C#,Asp.net,Asp.net Mvc,Entity Framework,我使用实体框架已经有一段时间了,我遇到了几个场景,其中两个上下文将尝试访问同一个实体等,因此我想知道我是否没有以最佳方式打开/关闭我的dbcontexts 目前,我基本上是按照基本MVC应用程序最初的设置方式在每个控制器上打开一个DbContext,这意味着我在控制器上有一个私有DbContext字段,我覆盖控制器的dispose方法来调用上下文上的dispose 然而,我有时也会在我的其他一些类中对db进行查询,这些类可以从控制器内部调用,控制器也有一个打开的上下文 有没有一种方法可以在没有显

我使用实体框架已经有一段时间了,我遇到了几个场景,其中两个上下文将尝试访问同一个实体等,因此我想知道我是否没有以最佳方式打开/关闭我的dbcontexts

目前,我基本上是按照基本MVC应用程序最初的设置方式在每个控制器上打开一个DbContext,这意味着我在控制器上有一个私有DbContext字段,我覆盖控制器的dispose方法来调用上下文上的dispose

然而,我有时也会在我的其他一些类中对db进行查询,这些类可以从控制器内部调用,控制器也有一个打开的上下文

有没有一种方法可以在没有显式处理程序的情况下访问开放上下文?对于我来说,通过十几种不同的方法传递DbContext引用是没有意义的。

处理
DbContext
实例的“最佳”方法是将它作为每个需要它的方法的参数(或者,如果整个类都需要它,则作为构造函数的参数)

这是IoC(控制反转)的一个基本部分,它允许调用方为方法指定依赖项,从而允许调用方“控制”被调用方法的行为

然后还可以添加依赖项注入框架。可以将它们配置为使用
DbContext
的单例实例,并将该实例注入任何需要它的方法。

处理
DbContext
实例的“最佳”方法是将它作为每个需要它的方法的参数(或者,如果整个类都需要它,则作为构造函数的参数)

这是IoC(控制反转)的一个基本部分,它允许调用方为方法指定依赖项,从而允许调用方“控制”被调用方法的行为


然后还可以添加依赖项注入框架。可以将它们配置为使用
DbContext的单例实例,并将该实例注入任何需要它的方法。

使用依赖项注入

正如其他人已经说过并且可能会重申的那样,“正确的方法”通常被认为是依赖注入

在我最新的项目中,我组织了一些事情,几乎完成了这个项目,DI非常轻松,我自己也在做(而不是使用注入器)。其中一个主要因素是相当严格地遵守这一结构:

                           WebProject
                             |    |
                             |   DataServices
                             |    |        | 
                           ViewModels    EntityModels
在一个工作单元中,通过单个DataServiceFactory实例访问所有数据服务,该实例需要MyDbContext实例。另一个因素是完全RESTful的应用程序设计——这意味着我不必在代码中穿插持久性功能

无依赖注入

也就是说,也许DI在这个项目上不适合你。也许:

  • 您不打算编写单元测试
  • 您需要更多的时间来理解DI
  • 您的项目结构已经深度集成
在ASP.NET MVC中,工作单元通常与请求生存期完全一致,即
HttpContext.Current
。因此,您可以为每个请求惰性地实例化存储库“singleton”,而不是使用DI。下面是一个经典的单例模式,当前上下文作为支持存储,用于保存您的
DbContext

public class RepositoryProxy {
    private static HttpContext Ctx { get { return HttpContext.Current; } }
    private static Guid repoGuid = typeof(MyDbContext).GUID;

    public static MyDbContext Context {
        get {
            MyDbContext repo = Ctx.Items[repoGuid];
            if (repo == null) {
                repo = new MyDbContext();
                Ctx.Items[repoGuid] = result;
            }
            return repo;
        }
    }

    public static void SaveIfContext() {
        MyDbContext repo = Ctx.Items[repoGuid];
        if (repo != null) repo.SaveChanges();
    }
}
如果你感觉特别懒,你也可以自动保存更改(当然,你仍然需要手动调用它来检查副作用,比如检索新项目的id):


使用依赖项注入

正如其他人已经说过并且可能会重申的那样,“正确的方法”通常被认为是依赖注入

在我最新的项目中,我组织了一些事情,几乎完成了这个项目,DI非常轻松,我自己也在做(而不是使用注入器)。其中一个主要因素是相当严格地遵守这一结构:

                           WebProject
                             |    |
                             |   DataServices
                             |    |        | 
                           ViewModels    EntityModels
在一个工作单元中,通过单个DataServiceFactory实例访问所有数据服务,该实例需要MyDbContext实例。另一个因素是完全RESTful的应用程序设计——这意味着我不必在代码中穿插持久性功能

无依赖注入

也就是说,也许DI在这个项目上不适合你。也许:

  • 您不打算编写单元测试
  • 您需要更多的时间来理解DI
  • 您的项目结构已经深度集成
在ASP.NET MVC中,工作单元通常与请求生存期完全一致,即
HttpContext.Current
。因此,您可以为每个请求惰性地实例化存储库“singleton”,而不是使用DI。下面是一个经典的单例模式,当前上下文作为支持存储,用于保存您的
DbContext

public class RepositoryProxy {
    private static HttpContext Ctx { get { return HttpContext.Current; } }
    private static Guid repoGuid = typeof(MyDbContext).GUID;

    public static MyDbContext Context {
        get {
            MyDbContext repo = Ctx.Items[repoGuid];
            if (repo == null) {
                repo = new MyDbContext();
                Ctx.Items[repoGuid] = result;
            }
            return repo;
        }
    }

    public static void SaveIfContext() {
        MyDbContext repo = Ctx.Items[repoGuid];
        if (repo != null) repo.SaveChanges();
    }
}
如果你感觉特别懒,你也可以自动保存更改(当然,你仍然需要手动调用它来检查副作用,比如检索新项目的id):


我建议您不要传递DbContext的实例,而是传递某种工厂类的实例,这将为您创建DbContext的实例

对于大多数场景,您只需创建DbContext将实现的接口,如下所示:

公共接口IDbContext
{
IDbSet Set(),其中tenty:class;
DbSet集合(类型entityType);
DbEntityEntry条目(TEntity实体),其中TEntity:class;
int SaveChanges();
}
然后返回一个工厂以返回您的实例:

公共接口IContextFactory
{
IDbContext检索();
}
可以很容易地模拟工厂以返回您想要的任何实现—这是一种很好的方法,尤其是如果您打算测试