EF对象的创建问题引发的几点思路

在开发过程中,项目往往被划分为多层,而一个请求过来往往从表示层开始一层一层向下调用,那么如果我们在不同的层中都使用到了EF上下文对象,而有好几层都这么创建一个EF对象然后对其进行操作,那么最终哪一层的EF对象是我们需要的最新的数据就很难确定了,这时就很容易产生脏读。在这种情况下,我们首先会想到使用单例模式,这样在整个应用程序的生命周期内只允许被创建一次。但是这样又会出现一个问题,所有的用户都访问同一个EF对象,随着访问的用户越来越多,这个EF对象的资源无法及时释放,导致占用的内存也会越来越大,虽然垃圾回收机制会自动回收掉大部分内存,但是有一些内存对象是需要我们手动回收的,可是在这里我们又不能使用using直接回收这个单例模式对象,因为如果把单例对象释放了,大家就都访问不了了,所以无法使用单例模式来解决这个EF对象创建问题。
这时,创建线程对象就可以了,我们只需要保证EF对象在一个线程内唯一,一个请求就是一个线程,这样就无须关心多层直接操作EF对象的问题了。HttpContext对象就是微软封装的一个线程对象,完全可以把创建的EF对象存到HttpContext对象中,实现EF对象在线程中唯一。

public MvcFirstCodeContext DB2{
    get{
        MvcFirstCodeContext db = null;
        if(HttpContext.Items["db1"]==null)
        {
            db = new MvcFirstCodeContext();
            HttpContext.Items["db1"]=db;
        }
        else{
            db = HttpContext.Items["db1"] as MvcFirstCodeContext;
            }
        return db;
}

多controller中的EF创建时,我们可以考虑把这个EF对象存到一个线程中,新建一个Base控制器,作为其它控制器的基类,然后让Home控制器继承自Base控制器,Base控制器中,添加命名空间引用:

using System.Runtime.Remoting.Messaging;

然后添加如下属性:

public MvcFirstCodeContext db
{
    get
    {
        MvcFirstCodeContext db = CallContext.GetData("DB") as MvcFirstCodeContext;
        if(db==null)
        {
            db = new MvcFirstCodeContext();
            CallContext.SetData("DB",db);
        }
        return db;
    }
}
  • 多次创建一个类的实例导致无法确定最终需要的是那个实例,进而导致数据脏读;

  • 使用单例导致对象占用资源无法被完全释放,进而导致垃圾过多,影响性能。

采取的措施是:每一个线程一个对象实例。

猜你喜欢

转载自blog.csdn.net/u010178308/article/details/82155148