在编写数据访问层代码之前,需要讨论下DbContext生命周期问题。一般在使用持久层框架延迟加载的环境中,DbContext生命周期需要做特殊维护,否则当实体对象传给DAO、Service至Action后,如果DbContext关闭,就无法访问延迟加载属性(如用户订单,产品留言等类似父子关系中的子表),一般系统就会抛出异常。
但在Spring.NET 与 NHibernate 整合时,可以很好的解决这个问题,这是因为Spring.NET为NHibernate提供了Session管理,在B/S构架下,可以在Web.Config中配置,以便让Spring来管理Session的打开与关闭,实际上就是在每一个Http请求时打开Session,而当这个Http请求结束时,才关闭Session。可以参考这篇:http://blog.csdn.net/xz2001/article/details/8518504
本篇的目的是写一个维护类,原理与Spring.NET处理NHibernate的Session类似,主要是提供EF框架中DbContext创建与销毁。
这里大概简述下实现原理:实现一个IHttpModule类,在Web请求时创建一个DbContext,并存储到HttpContext.Current.Items中,在其他项目中引用这个DLL,并可从HttpContext.Current.Items中读取DbContext;在Web请求结束后,销毁HttpContext.Current.Items中的DbContext实例。
1 创建一个新的解决方案
创建一个空的解决方案,并向其中创建一个类库项目,名称为“Simple.Web.EntityFramework5”,用于实现IHttpModule和管理DbContext对象。
看下我的项目:
上面两个项目不要关心,是我开发常用的封装,看第三个“Simple.Web.EntityFramework5”,开发时需要引用两个DLL,在Library目录中。
先看下DbContextHttpModule类:
using System; using System.Collections.Generic; using System.Web; using System.Text; namespace Simple.Web.EntityFramework5 { /// <summary> /// 处理 EF DbContext 对象的 Module 实现类。 /// </summary> public class DbContextHttpModule : IHttpModule { /// <summary> /// 构造函数。 /// </summary> public DbContextHttpModule() { } /// <summary> /// 初始化事件。 /// </summary> /// <param name="application">HttpApplication 对象。</param> public void Init(HttpApplication application) { application.BeginRequest += BeginRequest; application.EndRequest += EndRequest; } /// <summary> /// 销毁。 /// </summary> public void Dispose() { DbContextFactory.Dispose(); } /// <summary> /// 请求前事件。 /// </summary> /// <param name="sender">引发事件的对象。</param> /// <param name="e">事件对象。</param> protected void BeginRequest(object sender, EventArgs e) { DbContextFactory.InitContext(); } /// <summary> /// 请求后事件。 /// </summary> /// <param name="sender">引发事件的对象。</param> /// <param name="e">事件对象。</param> protected void EndRequest(object sender, EventArgs e) { } } }
再看DbContextFactory类:
using System; using System.Configuration; using System.Collections.Generic; using System.Web; using System.Text; using System.Data.Entity; using System.Data.Entity.Infrastructure; namespace Simple.Web.EntityFramework5 { /// <summary> /// DbContext 工厂类。 /// </summary> public class DbContextFactory { /// <summary> /// DbEntities 配置。 /// </summary> private static string dbKey = "EFDbEntity"; /// <summary> /// 存储于 Items 中的键名。 /// </summary> private static string itemKey = "DbContent_Key"; /// <summary> /// 构造函数。 /// </summary> static DbContextFactory() { dbKey = ConfigurationManager.AppSettings["EFDbEntity"]; } /// <summary> /// 初始化 DbContext 上下文。 /// </summary> public static void InitContext() { HttpContext.Current.Items[itemKey] = NewContext(); } /// <summary> /// 设置 DbContext 上下文。 /// </summary> /// <param name="context">DbContext 上下文。</param> public static void SetContext(DbContext context) { HttpContext.Current.Items[itemKey] = context; } /// <summary> /// 获取 DbContext 上下文。 /// </summary> /// <returns>DbContext 上下文。</returns> public static DbContext GetContext() { return (DbContext)HttpContext.Current.Items[itemKey]; } /// <summary> /// 新建 DbContext 上下文。 /// </summary> /// <returns>DbContext 上下文。</returns> public static DbContext NewContext() { return new DbContext("name=" + dbKey); } /// <summary> /// 销毁处理。 /// </summary> public static void Dispose() { if (HttpContext.Current.Items.Contains(itemKey)) { var context = (DbContext)HttpContext.Current.Items[itemKey]; context.Dispose(); HttpContext.Current.Items.Remove(itemKey); } } } }
2 使用方法
把刚才的项目编译成DLL(我的是:Simple.Web.EntityFramework5.dll),并在整合项目MESE.Dao、MESE.Web中引入进来。
然后配置Web.config文件,如下(仅是主要配置,请根据实际情况修改):
<configuration> <connectionStrings> <add name="SQLiteEntities" connectionString="metadata=res://*/SQLiteModel.csdl|res://*/SQLiteModel.ssdl|res://*/SQLiteModel.msl;provider=System.Data.SQLite;provider connection string="data source=F:\Administrator\文档\Visual Studio 2012\Projects\M3E4.1S1.3.2EF5SQLite\MESE.Web\App_Data\db.s3db"" providerName="System.Data.EntityClient" /> </connectionStrings> <appSettings> <add key="EFDbEntity" value="SQLiteEntities" /> </appSettings> <system.web> <httpModules> <!-- IIS6 中配置 --> <add name="OpenDbContext" type="Simple.Web.EntityFramework5.DbContextHttpModule, Simple.Web.EntityFramework5"/> </httpModules> </system.web> <system.webServer> <modules runAllManagedModulesForAllRequests="true"> <!-- IIS7 中配置 --> <add name="OpenDbContext" type="Simple.Web.EntityFramework5.DbContextHttpModule, Simple.Web.EntityFramework5"/> </modules> </system.webServer> </configuration>
注意:根据IIS版本不同,HttpModule配置的地方也不相同。
一旦完成上面的配置,即可通过DbContextFactory类来获取和创建DbContext对象了。
下一步开始编写数据访问层代码,请关注。