博客地址 http://blog.csdn.net/foxdave

本文主要记录近两天针对项目发生的数据访问问题的分析研究过程与系统架构优化,我喜欢说通俗的白话,高手轻拍

1. 发现问题

系统新模块上线后,使用频率较高,故在实际使用和后期的问题重现测试中,产生了一下系列的数据访问错误

错误是比较常见的错误

2. 分析问题

系统的架构为前端、业务层与数据层三层架构,采用Entity Framework 3.5作为数据处理技术,采用shared context per request模式,参照的是codeplex上的一个示例。示例地址(此文通俗易懂,代码结构也很清晰,个人很喜欢)

Entity模式的代码如下:

public partial class SPMIPEntities
{
public static SPMIPEntities Context
{
get
{
string objectContextKey = "MIP_" + HttpContext.Current.GetHashCode().ToString("x");
if (!HttpContext.Current.Items.Contains(objectContextKey))
{
HttpContext.Current.Items.Add(objectContextKey, new SPMIPEntities());
}
return HttpContext.Current.Items[objectContextKey] as SPMIPEntities;
}
}
}

基于以上,根据系统的报错位置研究Entity实例并发与共享的问题,搜索了一些entity framework相关的资料。此问题主要从两个角度去着手解决:缩短Entity实例的存在时间和降低Entity实例的共享性,并考虑性能,因为Entity需要手动Dispose。

首先添加手动Dispose逻辑,我们的项目为SharePoint应用程序,所以和一般的.net略有不同。自行开发了一个BasePage类,所有的应用程序页面都继承自该类,BasePage类又继承自LayoutsPageBase类,要做到使用完Entity后及时Dispose,最好也写在页面的类似结束请求的事件里,于是在后台敲上protected空格override空格D->发现可重写Dispose方法,大喜,代码如下:

public override void Dispose()
{
string objectContextKey = "MIP_" + HttpContext.Current.GetHashCode().ToString("x");
if (HttpContext.Current.Items.Contains(objectContextKey))
{
SPMIPEntities ctx = HttpContext.Current.Items[objectContextKey] as SPMIPEntities;
if (ctx != null)
{
ctx.Dispose();
HttpContext.Current.Items.Remove(objectContextKey);
}
}
base.Dispose();
}

修改之后部署,测试,发现报错了:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection

没理由会这样,因为每个请求都会实例化新的Entity,不可能会被提前释放。

调试代码,断点卡到第一段代码get下面。重启服务,访问系统,附加进程开始调试,第一次get进来了,new了一个Entity实例出去,页面加载了出来;刷新页面,发现没有再次中断,到这里,就非常的不合理了,肯定有忽视掉的地方,于是回过头来一层一层查看代码,发现业务层和数据层的类都被写成了单例模式,举例如下

public class DAC
{ #region 变量
// 本类对象
private static DAC _newNewInstance;
private SPMIPEntities ctx = null;
#endregion #region 构造函数 /// <summary>
/// 私有构造函数
/// </summary>
private DAC()
{
ctx = SPMIPEntities.Context;
} #endregion #region 公有方法 /// <summary>
/// 本类实例对象
/// </summary>
/// <returns>
/// 返回DAC对象
/// </returns>
public static DAC GetNewInstance()
{
if (_newNewInstance == null)
{
_newNewInstance = new DAC();
}
return _newNewInstance;
}
}

问题一定就在这里了,将单例模式改掉,修改为如下结构

public class DAC
{
private SPMIPEntities ctx = null; private DAC()
{
ctx = SPMIPEntities.Context;
} public static DAC GetNewInstance()
{
return new DAC();
}
}

修改完后部署重复上述步骤调试,预期中的结果。

下周再和团队一起系统地测试一遍,看看是不是有效果。

本来预期中的架构是没什么问题的,谁知当时又将操作类做成了单例模式而没有引起重视,为当前错误的爆发埋下了伏笔。架构还是应该多推敲,多考虑的。

要下班了,所以写的有些仓促;写得看起来很简单,但是研究的过程并不是特别简单,都是耗费时间的。特此记录。

Entity Framework 数据并发访问错误原因分析与系统架构优化的更多相关文章

  1. Entity Framework 处理并发

    Entity Framework 处理并发 在以前的两个教程你对关联数据进行了操作.本教程展示如何处理并发性.您将创建工作与各Department实体的 web 页和页,编辑和删除Department ...

  2. loadFileSystems error & ExceptionUtils错误原因分析

    loadFileSystems error & ExceptionUtils错误原因分析 一见 2014/5/7 C/C++程序通过hdfs.h访问HDFS,运行时遇到如下错误,会是什么原因了 ...

  3. "Entity Framework数据插入性能追踪"读后总结

    园友莱布尼茨写了一篇<Entity Framework数据插入性能追踪>的文章,我感觉不错,至少他提出了问题,写了出来,引起了大家的讨论,这就是一个氛围.读完文章+评论,于是我自己也写了个 ...

  4. MYSQL数据表损坏的原因分析和修复方法小结

    MYSQL数据表损坏的原因分析和修复方法小结 1.表损坏的原因分析 以下原因是导致mysql 表毁坏的常见原因: 1. 服务器突然断电导致数据文件损坏. 2. 强制关机,没有先关闭mysql 服务. ...

  5. “undefined reference to JNI_GetCreatedJavaVM”和“File format not recognized”错误原因分析

    "undefined reference to JNI_GetCreatedJavaVM"和"File format not recognized"错误原因分析 ...

  6. 深入了解Entity Framework框架及访问数据的几种方式

    一.前言 1.Entity Framework概要 Entity Framework是微软以ADO.NET为基础所发展出来的对象关系映射(O/R Mapping)解决方案.该框架曾经为.NET Fra ...

  7. EntityFramework_MVC4中EF5 新手入门教程之七 ---7.通过 Entity Framework 处理并发

    在以前的两个教程你对关联数据进行了操作.本教程展示如何处理并发性.您将创建工作与各Department实体的 web 页和页,编辑和删除Department实体将处理并发错误.下面的插图显示索引和删除 ...

  8. asp.net mvc常用的数据注解和验证以及entity framework数据映射

    终于有时间整理一下asp.net mvc 和 entity framework 方面的素材了. 闲话少说,步入正题: 下面是model层的管理员信息表,也是大伙比较常用到的,看看下面的代码大伙应该不会 ...

  9. .NET基础篇——Entity Framework 数据转换层通用类

    在实现基础的三层开发的时候,大家时常会在数据层对每个实体进行CRUD的操作,其中存在相当多的重复代码.为了减少重复代码的出现,通常都会定义一个共用类,实现相似的操作,下面为大家介绍一下Entity F ...

随机推荐

  1. thinkphp处理jQuery EasyUI form表单问题

    jQuery EasyUI form表单不是ajax方式提交,而是在提交的时候新建一个隐藏的iframe并在iframe里面创建一个与绑定表单一样的表单,然后在iframe里面进行同步提交而不是异步提 ...

  2. Flask系列之蓝图中使用动态URL前缀

    让我们先来看一个简单的例子,假设有下面这样一个蓝图(是关于用户主页的): from flask import Blueprint, render_template profile = Blueprin ...

  3. Openstack(三)Haproxy+Keepalived双机

    3.1部署keepalived 3.1.1下载keepalived源码包,并解压 # wget http://www.keepalived.org/software/keepalived-1.4.2. ...

  4. 【转】Deep Learning(深度学习)学习笔记整理系列之(二)

    因为我们要学习的是特征的表达,那么关于特征,或者说关于这个层级特征,我们需要了解地更深入点.所以在说Deep Learning之前,我们有必要再啰嗦下特征(呵呵,实际上是看到那么好的对特征的解释,不放 ...

  5. JS获取客户端系统当前时区

    <script> function getClientTimezone(){ var oDate = new Date(); var nTimezone = -oDate.getTimez ...

  6. Java基础知识 Set

    在Java中使用Set,可以方便地将需要的类型以集合类型保存在一个变量中.主要应用在显示列表.Set是一个不包含重复元素的 collection. 更确切地讲,set 不包含满足 e1.equals( ...

  7. 20155316 2016-2017-2 《Java程序设计》第8周学习总结

    教材学习内容总结 课堂部分要点 数据结构与算法 与 Java相结合 collection API:数据结构 crypt:密码学 操作系统 考试部分重点 实验楼:Linux第四节 教材:第6章.第14章 ...

  8. 使用ffmpeg进行网络直播

    一.采集:使用python调用摄像头采集,原设想是使用树莓派摄像头采集,但是经费紧张买不起,先用摄像头凑合下,反正很简单.                   原理就是先录一小段视频,然后循环播放,用 ...

  9. Jedis连接池

    jedis是官方首选的java客户端开发包 Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java.C.C#.C++.php.Node.js.Go等. 在官方网站里列一些Ja ...

  10. 《Java入门第二季》第三章 继承

    Java 中的继承1.作用:代码复用. 2.语法:extends关键字. 3.注意点:私有(private)财产(methods.fields)不可继承. Java 中的方法重写 Java 中的继承初 ...