C# 如何在没有显式引用的情况下访问OpenDBContext?
我使用实体框架已经有一段时间了,我遇到了几个场景,其中两个上下文将尝试访问同一个实体等,因此我想知道我是否没有以最佳方式打开/关闭我的dbcontexts 目前,我基本上是按照基本MVC应用程序最初的设置方式在每个控制器上打开一个DbContext,这意味着我在控制器上有一个私有DbContext字段,我覆盖控制器的dispose方法来调用上下文上的dispose 然而,我有时也会在我的其他一些类中对db进行查询,这些类可以从控制器内部调用,控制器也有一个打开的上下文 有没有一种方法可以在没有显式处理程序的情况下访问开放上下文?对于我来说,通过十几种不同的方法传递DbContext引用是没有意义的。处理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进行查询,这些类可以从控制器内部调用,控制器也有一个打开的上下文 有没有一种方法可以在没有显
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检索();
}
可以很容易地模拟工厂以返回您想要的任何实现—这是一种很好的方法,尤其是如果您打算测试