如何在没有显式引用的情况下访问打开的DbContext?
我现在一直在使用entity framework,并且我遇到了两个场景,其中两个上下文会尝试访问同一个实体等,所以我想知道是否我可能没有打开/关闭我的dbcontexts以最好的方式。
目前我基本上在每个控制器上打开一个DbContext,就像最初设置基本MVC应用程序一样,这意味着我在控制器上有一个私有dbcontext字段,并且我覆盖控制器的dispose方法来调用上下文中的dispose。
但是我有时也会在我的其他一些类中对db进行查询,这些类可以从控制器中调用,也可以打开上下文。
有没有办法在没有显式处理程序的情况下访问开放上下文? 通过十几种不同的方法传递DbContext引用对我来说真的没有意义。
使用dependency injection
正如其他人所说并且可能会重申的那样,“正确的方式”通常被认为是dependency injection。
在我的最新项目中,我已经组织了一些事情,所以我几乎完成了项目,而DI已经非常轻松,我自己就是这样做的(而不是使用注入器)。 其中一个主要因素是严格遵守这一结构:
WebProject | | | DataServices | | | ViewModels EntityModels
在一个工作单元期间访问所有数据服务是通过单个DataServiceFactory实例进行的,该实例需要MyDbContext的实例。 另一个因素是完全RESTful的应用程序设计 – 这意味着我不需要在整个代码中散布持久性function。
没有dependency injection
也就是说,也许DI在这个项目上不适合你。 也许:
在ASP.NET MVC中,工作单元通常完全符合请求生命周期 – 即HttpContext.Current
。 因此,您可以懒惰地为每个请求实例化存储库“单例”,而不是使用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(); } }
你也可以自动SaveChanges
,如果你感觉特别懒(你仍然需要手动调用它来检查副作用,当然,比如检索新项目的id):
public abstract class ExtendedController : Controller { protected MyDbContext Context { get { return RepositoryProxy.Context; } } protected override void OnActionExecuted(ActionExecutedContext filterContext) { RepositoryProxy.SaveIfContext(); base.OnActionExecuted(filterContext); } }
处理DbContext
实例的“最佳”方法是使其成为需要它的每个方法的参数(或者,如果整个类需要它,则为构造函数的参数)。
这是IoC(控制反转)的基本部分,它允许调用者指定方法的依赖关系,从而允许调用者“控制”被调用方法的行为。
然后,您还可以添加dependency injection框架。 它们可以配置为使用DbContext
的单例实例,并将该实例注入任何需要它的方法。
我建议您传递某种工厂类的实例,而不是传递DbContext的实例,这将为您创建一个DbContext实例。
对于大多数情况,您只需创建DbContext将实现的接口,如下所示:
public interface IDbContext { IDbSet Set () where TEntity : class; DbSet Set(Type entityType); DbEntityEntry Entry (TEntity entity) where TEntity : class; int SaveChanges(); }
然后工厂返回你的实例:
public interface IContextFactory { IDbContext Retrieve(); }
工厂可以很容易地被模拟以返回你想要的任何实现 – 这是一个很好的方法,特别是如果你打算测试应用程序。 您的DbContext
将从IDbContext
接口派生并实现必要的方法和属性。 这种方法假设,告诉EF你的数据库表你使用OnModelCreating(DbModelBuilder modelBuilder)
方法和modelBuilder.Configurations.Add(new EntityTypeConfiguratinOfSomeType());
而不是在您的上下文中DbSet
类型的属性。
要从Entity框架中完全抽象,您可以创建另一个抽象层,例如使用UnitOfWork或Repository模式方法,但我想前者现在涵盖了您的关注点。
上述就是C#学习教程:如何在没有显式引用的情况下访问打开的DbContext?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1015867.html