Entity Framework在Asp.net MVC中的实现One Context Per Request(转)

上篇中"Entity Framework中的Identity map和Unit of Work模式", 因为EF中的Identity map和Unit of Work模式,EF体现出来以下特性:html

惟一性: 在一个Context的生命周期中,一个Entity只会有一个实例,任何对该实例的修改,即便这些改动没有保存到数据库中,修改都会影响到整个Context的生命周期。数据库

事务性: 全部对于Entity的修改,都会在调用SaveChange方法的时候,一块儿保存到数据库中,最终实现持久化。缓存

下面基于EF的上面特色,分析一下为何须要在MVC中实现One Context Per Request, 也就是在一个Request生命周期中,只有一个Context.函数

阅读目录:性能

1、每次建立Context的缺点ui

2、使用全局Context的缺点spa

3、在MVC中实现One Context Per Request.net

4、借助Autofac实现One Context Per Requestcode

一,每次建立Context的缺点

通常在项目的数据访问层中使用Entity Framework,代码以下orm

复制代码
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容器提供 
复制代码
相关文章
相关标签/搜索