Entity Framework在Asp.net MVC中的实现One Context Per Request(转)
上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现出来如下特性:
唯一性: 在一个Context的生命周期中,一个Entity只会有一个实例,任何对该实例的修改,即使这些改动没有保存到数据库中,修改都会影响到整个Context的生命周期。
事务性: 所有对于Entity的修改,都会在调用SaveChange方法的时候,一起保存到数据库中,最终实现持久化。
下面基于EF的上面特点,分析一下为什么需要在MVC中实现One Context Per Request, 也就是在一个Request生命周期中,只有一个Context.
阅读目录:
一、每次创建Context的缺点
二、使用全局Context的缺点
三、在MVC中实现One Context Per Request
四、借助Autofac实现One Context Per Request
一,每次创建Context的缺点
一般在项目的数据访问层中使用Entity Framework,代码如下

public IEnumerable<Student> GetStudents()
{
using (var context = new SchoolContext())
{
return context.Students.ToList();
}
}

这个是数据访问层中非常常见的方法,返回DB中所有的Student数据。
这里在使用Context的时候,创建一个Context的实例进行操作。
但是这种方式带来了下面一些缺点:
- 首先,每次的数据处理,都用new context, 会导致更多的资源开销。
- 假如业务逻辑层调用GetStudents方法获取到数据之后,要访问Student的导航属性School怎么办? 逻辑层代码使用导航时候就会导致异常,因为EF只能在context生命周期中,才能够再次请求数据库,取得导航属性School的数据。
- 如果是插入操作,而且是多个关联表的数据插入,插入操作在不同的context中完成,就无法应用EF的事务效果。保证数据能够同时插入成功,如果失败,就一起回滚。
- 如果在循环中插入数据,每次插入数据都是在不同的context中完成,性能就是一个悲剧。
二,使用全局Context的缺点
看到了"每次创建Context”的缺点,可能会认为使用全局Context是个好的解决方案。
但是全局Context带来的问题更大:
- 如果全局使用一个Context,会导致越来越多的数据缓存到本地, 随着程序的使用时间越长,占用的资源越来越大。
- 使用全局Context, 会导致缓存数据无法得到及时更新。即使数据库中的数据有改动,使用EF取出来得数据有可能还是改动之前的数据。
所以:
- 在MVC项目中,建议每个request, 使用一个Context
- 在Winform中和WPF中,一个Form或者一个Presenter一个Context
- 在WebService, Web API中,每次调用, 使用一个Context.
三, 在MVC中实现One Context Per Request
思路是这样的, 在Global.asax.cs文件中,在Begin Request事件中,创建和保存Context; 在End Request事件中,销毁Context. 另外提供一个公开的静态属性来获取这个Context。
详细的代码如下:
在Global.asax.cs中

protected virtual void Application_BeginRequest()
{
HttpContext.Current.Items["_EntityContext"] = new EntityContext();
} protected virtual void Application_EndRequest()
{
var entityContext = HttpContext.Current.Items["_EntityContext"] as EntityContext;
if (entityContext != null)
entityContext.Dispose();
}

添加静态属性,以便程序中能够方便的取出和使用Context

public class EntityContext
{
public static EntityContext Current
{
get { return HttpContext.Current.Items["_EntityContext"] as EntityContext; }
}
}

四,借助Autofac实现One Context Per Request
Autofac是.net的Ioc容器,具体使用的方法,可以看这里 IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)
本文的Demo源码,是在上面博客附带的源码基础上修改而来的。
这里,只是介绍一下如何使用Autofac注册Context
在Application_Start函数体内,执行如下代码

var builder = new ContainerBuilder(); //创建builder
//注册builder, 实现one context per request
builder.RegisterType<eassistdevContext>().InstancePerHttpRequest(); var container = builder.Build();//创建容器
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));//覆盖MVC默认的实例化Controller的方法,转而又Auotfac容器提供

Entity Framework在Asp.net MVC中的实现One Context Per Request(转)的更多相关文章
- Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)
上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...
- Asp.Net MVC4开发二: Entity Framework在Asp.Net MVC4中的应用
ORM作为一种数据库訪问机制已广泛地应用于各种项目其中,在.Net开发中,应用比較广泛的ORM框架大致有以下几个: 官方支持的有:Linq to SQL.Entity Framework.三方的有:N ...
- devexpress entity framework 与 asp.net mvc的坑
最近在做一个使用ASP.NET MVC DEVEXPRESS和EF的OA模块 遇到不少问题这里记录一下: 1 如果项目中存在多个上下文类(DBContext的派生类),在做数据迁移的时候需要在不同目录 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (20) -----第四章 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第四章 ASP.NET MVC中使用实体框架 ASP.NET是一个免费的Web框架 ...
- 在ASP.NET MVC中实现基于URL的权限控制
本示例演示了在ASP.NET MVC中进行基于URL的权限控制,由于是基于URL进行控制的,所以只能精确到页.这种权限控制的优点是可以在已有的项目上改动极少的代码来增加权限控制功能,和项目本身的耦合度 ...
- ASP.NET Identity系列02,在ASP.NET MVC中增删改查用户
本篇体验在ASP.NET MVC中使用ASP.NET Identity增删改查用户. 源码在这里:https://github.com/darrenji/UseIdentityCRUDUserInMV ...
- ASP.NET MVC中使用窗体验证出现上下文的模型在数据库创建后发生更改,导致调试失败(一)
在ASP.NET MVC中使用窗体验证.(首先要明白,验证逻辑是应该加在Model.View和Controller哪一个里面?由于Model的责任就是负责信息访问与商业逻辑验证的,所以我们把验证逻辑加 ...
- ASP.NET Core 配置 Entity Framework Core - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 配置 Entity Framework Core - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 配置 Entity Fram ...
- ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器
ASP.NET MVC 中应用Windows服务以及Webservice服务开发分布式定时器一:闲谈一下:1.现在任务跟踪管理系统已经开发快要结束了,抽一点时间来写一下,想一想自己就有成就感啊!! ...
随机推荐
- Sql视图创建语句及修改视图
create view [dbo].[AllUsers] as select u.UserId, u.Firstname, u.Lastname, u.ts, am.Email, au.UserNam ...
- 模拟和数字低通滤波器的MATLAB实现
低通滤波器参数:Fs=8000,fp=2500,fs=3500,Rp=1dB,As=30dB,其他滤波器可以通过与低通之间的映射关系实现. %%模拟滤波器 %巴特沃斯——滤波器设计 wp=2*pi*2 ...
- Angular $httpProvider
timeout超时响应 .factory('timestampMarker', ["$rootScope", function () { var timestampMarker = ...
- java锁之wait,notify(wait会释放锁,notify仅仅只是通知,不释放锁)
wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法 ...
- 已经mock类中引用的其它service类,但是在invoke私有方法的时候,该service类是空值
错误原因:没有在开始测试用例的时候,初始化类的所有注解方法. 解决方法: 使用mock方法创建mock对象时,需要在测试用例执行前执行以下代码.通常, 这句代码可以放在测试基类或者@Before 中. ...
- LeetCode 206. Reverse Linked List(迭代和递归两种实现)
递归的代码比迭代的代码看起来更清爽一些,也是由于递归对行为进行了抽象吧. 注意到,这是一个尾递归函数.一些编译器会将它优化为迭代,这样一方面,在代码层面保持了清晰的逻辑和可读性.一方面保持了代码的性能 ...
- 【ubantu】在Ubuntu上安装tar.gz,tar.bz以及deb文件(例:libreoffice安装)
参考文章: https://blog.csdn.net/zhuquan945/article/details/52986712 ==================================== ...
- SecureCRT 设置字体跟颜色
SecureCRT 绝佳配色方案, 保护你的眼睛 分类: Linux 软件使用2013-05-17 08:45 24038人阅读 评论(11) 收藏 举报 SecureCRT 绝佳配色方案, 保护你的 ...
- ShareSDK 微博空间分享
本文转载至 http://blog.csdn.net/learnios/article/details/8992346 ShareSDK微博分享空间分享新浪微博腾讯微博 第一步:首先导入ShareSD ...
- 九度OJ 1350:二叉树的深度 (二叉树)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1044 解决:614 题目描述: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长 ...