EF中DataContext以及对应实体的生命周期

Enitity Framework的文章非常多,而且使用起来也非常简单。当然一旦遇到一个异常时,就非常让人头疼。最近一直用EF,遇到一些问题,所以分享出来对大家或许有些帮助。在这里不会研究源码,只说原理,并分享一些最佳实践的代码。有说的不对的地方,请过路人指正。

DataContext对象应该生成多少个?

当我们new一个新的DataContext对象并从数据库获取相关实体时,意味着DataContext会对这些获取到的实体进行状态跟踪。本质上讲,你只得到数据库某个数据的一个拷贝。当你对实体进行增加删除时,实体本身并没有进行增删改,但DataContext会把这些状态都记录下来;一旦调用dbContext.SaveChanges(),DataContext才会生成对应sql命令,把这些更改保存到数据库中。如果你以为这是理所当然的事情,那么请看下面一个例子:

User user = null;
using(MyDataContext context = new MyDataContext())
{
   user = context.Users.First();
}
user.Age = 18;

using(MyDataContext context2 = new MyDataContext())
{
   context2.Entry<User>(user).State = EntityState.Modified;
   context2.SaveChanges();
}

这里会抛出一个异常。异常是:An entity object cannot be referenced by multiple instances of IEntityChangeTracker。IEntityChangeTracker相当于实体的跟踪器。一个DataContext管理了另一个DataContext下的实体,这是不允许的。打个比方说,DataContext就像一个国王,负责他的子民的生老病死,另一个国家的国王是不能对本国的子民进行审判的,这是越界了,要引发战争的。【可以通过Attach和DeAttach来修改国籍,达到被另一个DataContext管理的目的】这么看来,在一个应用里似乎只需要一个国王就能搞定所有事情,事实是不是这样的呢?

上面说过,每个通过同一个DataContext得到的实体都会被它跟踪管理,那么如果多个客户端都使用一个DataContext获取实体,而又都在各自的客户端更改,当同时提交SaveChanges时,哦,麻烦出现了。永远不要出现单例的DataContext用在应用程序环境里,那会导致各种错误,最基本的是线程不安全,你对国王的各种奏章导致他分身乏术,出现并发冲突。

那么在一个应用里,要有多少个国王DataContext才行呢?

根据各种经验显示,对Asp.Net网站,应该是每一个请求一个DataContext,对于Winform以及WPF应该是每个窗体或表现一个DataContext,对于WebService应该是每个调用一个DataContext

对于Asp.Net网站,因为是一个请求一个DataContext,所以我们可以保存到HttpRequst的缓存中,保证了DataContext的唯一性。最佳实践代码如下:

public static MyDataContext Instance
 {
     get
     {
         if (HttpContext.Current != null && HttpContext.Current.Cache["MyDataContext "] == null)
         {
             HttpContext.Current.Cache["MyDataContext "] = new MyDataContext ();
         }
         return HttpContext.Current.Cache["MyDataContext "] as MyDataContext ;
     }
     set { 
         if(HttpContext.Current != null)
             HttpContext.Current.Cache["MyDataContext "] = value; 
     }
 }

对于winform或WPF,可以使用如下代码:

[ThreadStatic]
private static MyDataContext instance;

public static MyDataContext Instance(){
    if (context == null)
        instance= new MyDataContext ();
    return instance;
}

使用ThreadStatic保证线程安全,为什么在asp.net下不使用这个属性来确保安全呢?是因为IIS下有重用线程的可能性,对于另一个请求,IIS会继续使用这个DataContext进行操作,那么,你看,又会并发冲突了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值