昨天遇到一段棘手的程序,尝试了各种方法,忽而在SubmitChanges的时候没反应(无错误,也不更新),忽而发生ChangeConflict,经过几个小时,终于大致理清了思路,也顺便把DataContext/UpdateModel/SubmitChanges给搞得更明白了一些,特此分享。

先大致看看代码:

xxController

{

AgileRepository _repAgile = new AgileRepository(); //这里边是SubmitChanges/DateContext/Tables等属性,可取出下面提到的story
        SFCRepository _repSFC = new SFCRepository(); //相同,可取出下面提到的UDCs

[HttpPost]
        public ActionResult Edit(int id, FormCollection collection)
        {
            Story story = _repAgile.GetStoryAt(id);

try
            {
                UpdateModel(story);
                foreach (var udc in story.UDCs)
                {
                    UpdateModel(udc, udc.ID.ToString("D6"));
                }
                _repAgile.Save();

_repSFC.Save(); //这里也是
                ...
            }
}

之所以出现红色的_repSFC.Save(),是因为story的一个属性List<IUDC> UDCs,也是需要在这个页面被更新的内容(在View中有控件与其对应),而它的Get过程最初是:

class Story

{

public List<IUDC> UDCs 
        {
            get
            {

SFCRepository rep = new SFCRepository(); 
                return rep.GetUDCs().Where(...);
            }
            set { }
        }
}

这里蓝色的rep和前面红色的rep不是同一个,所以如果从蓝色rep的当中取出UDCs并进行UpdateModel,而对另外一个无关的红色rep保存,什么也不会发生;而如果两者都取出UDCs并都曾经被UpdateModel,在Save(内部执行了SubmitChanges)的时候,会报出confilict changes exception,这个Exception极其麻烦而且不透明Google/MSDN上能找到一些资料但很多不工作。

其实,全部解决方法的秘诀其实就是:让取出数据的那个Repository执行Save操作(或者从内部看,是让取出数据的DataContext执行SubmitChanges操作)

蓝色rep的是个局部变量,活不到Save的时候了,只能用红色的那个rep了。代码改为下面这个就好了:

xxController

{

SFCRepository _repSFC = new SFCRepository(); //下面取数据/保存的都是它。

[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    Story story = _repAgile.GetStoryAt(id);

_repSFC.GetUDCsFor(story); //在这里边让_repSFC的DataContext取数据。

try
    {
        UpdateModel(story);
        foreach (var udc in story.UDCs)
        {
             UpdateModel(udc, udc.ID.ToString("D6"));
        }
        _repAgile.Save();

_repSFC.Save(); //这里会完成存储。
        ...
}

尽管能用了,但这段代码很不好,尤其GetUDCsFor,调用的位置很生硬,不好读也很容易出错。

最终还是这样最好:

外面:

Story story = _repAgile.GetStoryAt(id);

try
            {
                UpdateModel(story);
                foreach (var udc in story.UDCs)
                {
                    UpdateModel(udc, udc.ID.ToString("D6")); //Update的
                }
                story.SaveUDCs(); // 这个调用看着顺眼。
                _repAgile.Save();
                ...
            }
里边:

public partial class Story : IUDCable, IItem
    {

private SFCRepository _repSFC = new SFCRepository(); //这个方案里取数据/保存的都是它。_repSFC不再是个局部变量,生命周期正好和UDCs相同。
        public void SaveUDCs()
        {
            _repSFC.Save(); // 在这里保存
        }
        public List<IUDC> UDCs 
        {
            get
            {
                _repSFC.GetUDCOf(this, ref _udcs); //取数据。
                return _udcs;
            } 
        }
后面本来不应该再把_udcs传入GetUDCOf了,直接但因为别的IUDCable也要用到,所以封装了一个函数。

这个方案,取数据/存数据的都是Story内部的_repSFC,而且封装性更好,是最终结果。

最后重复一下在这种场景中发生问题时的解决方法的秘诀其实就是:让取出数据的那个Repository执行Save操作(或者从内部看,是让取出数据的DataContext执行SubmitChanges操作)

点击下载免费的敏捷开发教材:《火星人敏捷开发手册》

转载于:https://www.cnblogs.com/JPAORM/archive/2011/05/31/2510496.html

从一个案例看MVC中DataContext和UpdateModel的工作原理(详解UpdateModel/SubmitChanges错误)...相关推荐

  1. Computer:字符编码(ASCII编码/GBK编码/BASE64编码/UTF-8编码)的简介、案例应用(python中的编码格式及常见编码问题详解)之详细攻略

    Computer:字符编码(ASCII编码/GBK编码/BASE64编码/UTF-8编码)的简介.案例应用(python中的编码格式及常见编码问题详解)之详细攻略 目录 符串编码(ASCII编码/GB ...

  2. Java生成随机数原理_Java中随机数的产生方式与原理详解

    Java中随机数的产生方式与原理 查阅随机数相关资料,特做整理 首先说一下java中产生随机数的几种方式 在j2se中我们可以使用Math.random()方法来产生一个随机数,这个产生的随机数是0- ...

  3. 并联谐振电路工作原理详解,案例+计算公式,几分钟带你搞定

    昨天给大家分享了关于串联谐振的文章,今天给大家分享关于并联谐振的文章.(私信我的那个朋友,记得准备来看) 错过了串联谐振的朋友,可以直接点击下方标题跳转. 串联谐振是怎么工作的?案例+公式,几分钟,一 ...

  4. 三极管的工作原理详解,图文+案例

    什么是三极管? 三极管全称是"晶体三极管",也被称作"晶体管",是一种具有放大功能的半导体器件.通常指本征半导体三极管,即BJT管. 典型的三极管由三层半导体材 ...

  5. java 事务实现原理_Spring中事务用法示例及实现原理详解

    前言 Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现. 关于事务,简单来说,就是为了保证数据 ...

  6. JavaScript中sort方法的使用及原理详解

    原生JS中提供了两个用来重排序的方法:reverse()和sort(),reverse()没什么好说的,就是直接使数组反转,例如下面的栗子: var arr = [1, 2, 3, 4, 5, -1, ...

  7. 深度:一文看懂Linux内核,Linux内核架构和工作原理详解

    简介 作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址.目前支持模块的动态装卸(裁剪).Linux内核就是基于这个策略实现的.Linux进程1.采用层次结构,每个 ...

  8. 一文看懂Linux内核!Linux内核架构和工作原理详解

    linux内核相关视频解析: 5个方面分析linux内核架构,让你对内核不再陌生 90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc的原理 手把手带你实现一个Linux内核 ...

  9. 深度:一文看懂Linux内核!Linux内核架构和工作原理详解

    简介 作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址.目前支持模块的动态装卸(裁剪).Linux内核就是基于这个策略实现的.Linux进程1.采用层次结构,每个 ...

最新文章

  1. 怎么安装linux系统 硬盘,如何实现硬盘安装linux系统
  2. 面试题:mysql 表删除一半数据,B+树索引文件会不会变小???
  3. CG CTF WEB Download~!
  4. python 打包exe_python如何封装为exe
  5. java 保留字符串,如何在Java中保留字符串而不使用反转功能
  6. 三种强大的物体识别算法——SIFT/SURF、haar特征、广义hough变换的特性对比分析
  7. 使用宝塔控制面板建站时出现网页出现404错误怎么办?
  8. 英语学习回炉之绕口令
  9. 编程中遇到的优秀网站收藏
  10. 鸿蒙系统适配的电视,搭载鸿蒙系统的荣耀智慧屏电视适配app太少?网友:感觉上当了...
  11. 小红书数据平台:笔记爆文率提升的三大秘诀公式!
  12. python爬虫--小说爬取
  13. 谷歌和哈佛团队用深度学习预测余震;谷歌移交 Kubernetes 管理权,并承诺资助 900 万美元...
  14. 【Java基础】【练习题6】static练习
  15. 可交易性(tradability)检验即协整性检验:介绍
  16. Maven Plugin fork 在 pom.xml中的作用
  17. linux监听端口命令
  18. Arduino人体红外感应+继电器
  19. maven仓库读取顺序
  20. rk3568 适配摄像头 (双摄)

热门文章

  1. 【解决】Oracle服务器ip地址被占用
  2. 如何查看网页缓存的密码
  3. 通过升级.NET框架提升实体框架性能
  4. zz详细讲解Quartz.NET
  5. Box2DWeb_03之Shape
  6. Android中使用Intent进行窗体切换,并且传值和自定义类的对象详解
  7. 东航期货穿透接口相关资料
  8. php 获取当前action,ThinkPHP3.2.2获取当前Action名称
  9. 电子城西区北扩规划一路道路工程_雁塔区电子城街道重点项目进度
  10. 决策树 随机森林 xgboost_从决策树到随机森林理论篇从人话到鬼话:看不懂来找我麻烦...