Entity Framework 数据并发访问错误原因分析与系统架构优化

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

1. 发现问题

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

错误是比较常见的错误

2. 分析问题

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

Entity模式的代码如下:

[csharp] view plaincopyprint?

  1. public partial class SPMIPEntities
  2. {
  3. public static SPMIPEntities Context
  4. {
  5. get
  6. {
  7. string objectContextKey = "MIP_" + HttpContext.Current.GetHashCode().ToString("x");
  8. if (!HttpContext.Current.Items.Contains(objectContextKey))
  9. {
  10. HttpContext.Current.Items.Add(objectContextKey, new SPMIPEntities());
  11. }
  12. return HttpContext.Current.Items[objectContextKey] as SPMIPEntities;
  13. }
  14. }
  15. }

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

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

[csharp] view plaincopyprint?

  1. public override void Dispose()
  2. {
  3. string objectContextKey = "MIP_" + HttpContext.Current.GetHashCode().ToString("x");
  4. if (HttpContext.Current.Items.Contains(objectContextKey))
  5. {
  6. SPMIPEntities ctx = HttpContext.Current.Items[objectContextKey] as SPMIPEntities;
  7. if (ctx != null)
  8. {
  9. ctx.Dispose();
  10. HttpContext.Current.Items.Remove(objectContextKey);
  11. }
  12. }
  13. base.Dispose();
  14. }

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

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

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

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

[csharp] view plaincopyprint?

  1. public class DAC
  2. {
  3. #region 变量
  4. // 本类对象
  5. private static DAC _newNewInstance;
  6. private SPMIPEntities ctx = null;
  7. #endregion
  8. #region 构造函数
  9. /// <summary>
  10. /// 私有构造函数
  11. /// </summary>
  12. private DAC()
  13. {
  14. ctx = SPMIPEntities.Context;
  15. }
  16. #endregion
  17. #region 公有方法
  18. /// <summary>
  19. /// 本类实例对象
  20. /// </summary>
  21. /// <returns>
  22. /// 返回DAC对象
  23. /// </returns>
  24. public static DAC GetNewInstance()
  25. {
  26. if (_newNewInstance == null)
  27. {
  28. _newNewInstance = new DAC();
  29. }
  30. return _newNewInstance;
  31. }
  32. }

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

[csharp] view plaincopyprint?

  1. public class DAC
  2. {
  3. private SPMIPEntities ctx = null;
  4. private DAC()
  5. {
  6. ctx = SPMIPEntities.Context;
  7. }
  8. public static DAC GetNewInstance()
  9. {
  10. return new DAC();
  11. }
  12. }

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

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

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

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

时间: 2024-09-30 15:10:57

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

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

终于有时间整理一下asp.net mvc 和 entity framework 方面的素材了. 闲话少说,步入正题: 下面是model层的管理员信息表,也是大伙比较常用到的,看看下面的代码大伙应该不会陌生, 在此Model上我们用到了asp.net mvc的数据注解和验证,entity framework对数据库的映射 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.T

Golang适合高并发场景的原因分析

典型的两个现实案例: 我们先看两个用Go做消息推送的案例实际处理能力. 360消息推送的数据: 16台机器,标配:24个硬件线程,64GB内存 Linux Kernel 2.6.32 x86_64 单机80万并发连接,load 0.2~0.4,CPU 总使用率 7%~10%,内存占用20GB (res) 目前接入的产品约1280万在线用户 2分钟一次GC,停顿2秒 (1.0.3 的 GC 不给力,直接升级到 tip,再次吃螃蟹) 15亿个心跳包/天,占大多数. 京东云消息推送系统 (团队人数:4

&quot;Entity Framework数据插入性能追踪&quot;读后总结

园友莱布尼茨写了一篇<Entity Framework数据插入性能追踪>的文章,我感觉不错,至少他提出了问题,写了出来,引起了大家的讨论,这就是一个氛围.读完文章+评论,于是我自己也写了个简单的程序试了试. 先晒一下代码: 两个简单的类: 1: /// <summary> 2: /// 消费者 3: /// </summary> 4: public class Consumer 5: { 6: public int CId { get; set; } 7: public

高并发高负载的大型网站系统架构(转)

高并发高负载的大型网站系统架构(转) 一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构.性能的要求都很简单,随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件.编程语言.数据库.WebServer.防火墙等各个领域都有了很高的要求,已经不是原来简单的html静态网站所能比拟的. 大型网站,比如门户网站

高并发高负载的大型网站系统架构

大型网站的系统架构需要考虑很多问题.大型网站有高并发高负载的特点,在面对大量用户访问.高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器.高性能的数据库.高效率的编程语言.还有高性能的Web容器.本文从低成本.高性能和高扩张性的角度来探讨了一些大型网站系统架构需要考虑的问题. AD:WOT2014:用户标签系统与用户数据化运营培训专场 一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统

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

一.前言 1.Entity Framework概要 Entity Framework是微软以ADO.NET为基础所发展出来的对象关系映射(O/R Mapping)解决方案.该框架曾经为.NET Framework的一部分,但Version 6之后从.NET Framework分离出来,可通过NuGet获取. Entity Framework利用抽象化数据结构的方式,将每个数据库对象都转换成应用程序对象 (Entity),而数据字段都转换为属性 (Property),关系则转换为结合属性 (Ass

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

在以前的两个教程你对关联数据进行了操作.本教程展示如何处理并发性.您将创建工作与各Department实体的 web 页和页,编辑和删除Department实体将处理并发错误.下面的插图显示索引和删除的页面,包括一些如果发生并发冲突,则显示的消息. 并发冲突 当一个用户要编辑它,显示实体数据,然后另一个用户更新相同的实体数据第一个用户的更改写入到数据库之前,将发生并发冲突.如果您不启用此类冲突检测,最后谁更新数据库覆盖其他用户的更改.在许多应用中,这种风险是可以接受: 如果有几个用户或一些更新,

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

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 在实现基础的三层开发的时候,大家时常会在数据层对每个实体进行CRUD的操作,其中存在相当多的重复代码.为了减少重复代码的出现,通常都会定义一个共用类,实现相似的操作,下面为大家介绍一下Entity Framework时常用到的通用类.首先在数据

SQL Server 磁盘请求超时的833错误原因分析以及解决

本文出处:http://www.cnblogs.com/wy123/p/6984885.html 最近遇到一个SQL Server服务器响应极度缓慢,并且出现客户端请求报错的情况,在数据库中的errorlog中出现磁盘请求超过一定时间才完成的error消息.对于此类问题,到底是存储系统或者磁盘的故障,还是SQL Server 自己的问题,亦或是应用程序引发的呢?又要如何解决?本文将对引起此问题的某一方面的因素进行简单的分析,但是无法涵盖所有潜在的可能性,因此遇到类似问题还要做具体的分析. SQL