ExtJS4.1+MVC3+Spring.NET1.3+EF5 整合四:DbContext生命周期

22 篇文章 0 订阅
16 篇文章 0 订阅

在编写数据访问层代码之前,需要讨论下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实例。 

另外,存储DbContext实例还可以使用另一个类 --CallContext,稍后也将说下实现。  

1 创建一个新的解决方案

创建一个空的解决方案,并向其中创建一个名称为“Simple.Web.EntityFramework5”的类库项目,用于实现IHttpModule和管理DbContext对象。

看下我的项目:


上面两个项目不要关心,是我开发常用的封装,看第三个“Simple.Web.EntityFramework5”,开发时需要引用两个DLL,在Library目录中。

1.1 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)
        {
        }
    }
}

1.2 DbContextFactory类:

1.2.1 HttpContext实现
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);
            }
        }
    }
}
1.2.2 CallContext实现
using System;
using System.Configuration;
using System.Collections.Generic;
using System.Web;
using System.Text;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Runtime.Remoting.Messaging;

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()
        {
            SetContext(NewContext());
        }

        /// <summary>
        /// 设置 DbContext 上下文。
        /// </summary>
        /// <param name="context">DbContext 上下文。</param>
        public static void SetContext(DbContext context)
        {
            DbContext db = CallContext.GetData(itemKey) as DbContext;
            if (db == null)
            {
                CallContext.SetData(itemKey, context);
            }
        }

        /// <summary>
        /// 获取 DbContext 上下文。
        /// </summary>
        /// <returns>DbContext 上下文。</returns>
        public static DbContext GetContext()
        {
            DbContext db = CallContext.GetData(itemKey) as DbContext;
            if (db == null)
            {
                InitContext();
            }

            return CallContext.GetData(itemKey) as DbContext;
        }

        /// <summary>
        /// 新建 DbContext 上下文。
        /// </summary>
        /// <returns>DbContext 上下文。</returns>
        public static DbContext NewContext()
        {
            return new DbContext("name=" + dbKey);
        }

        /// <summary>
        /// 销毁处理。
        /// </summary>
        public static void Dispose()
        {
            DbContext db = CallContext.GetData(itemKey) as DbContext;
            if (db != null)
            {
                CallContext.FreeNamedDataSlot(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对象了。


下一步开始编写数据访问层代码,请关注。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值