Linq中的陷阱问题(折磨了好几天)

简介: Linq2SQL中一个经典的Exception Info: System.Data.Linq.ChangeConflictException异常过程。

最近在程序运行中,发生一个比较怪异的问题导致程序异常退出(崩溃),开始没注意,以为是偶发问题。后来变成了必再现问题。查看Windows事件日志异常如下:

Application: XXXXX.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Data.Linq.ChangeConflictException
Stack:
   at System.Data.Linq.DataContext.SubmitChanges(System.Data.Linq.ConflictMode)
   at NMS.PPC.DataSource.Database.DBOperator.SubmitChanges()

开始也没在意。觉得这个没什么,就是数据库更新时异常了。加个try-catch就解决了。结果发现另一个功能也发生了这个问题。由于Windows日志中没有抛出具体的Message,使用WinDebug分析Dump文件,看到了具体的消息,如下:

Exception object: 0000000010f87f48
Exception type:   System.Data.Linq.ChangeConflictException
Message:          找不到行或行已更改。
InnerException:   <none>

要更新的行明明存在怎么能找不到。我没更改呢,所以已更改不太可能发生。
因为研发环境无法再现,就将测试环境中的数据库和数据拿回到研发环境中,很快就再现了。确定问题确实存在。通过Linq输出SQL语句,发生所有的字段都在Where条件中出现了(这可能是Linq慢的原因吧)。
然后百度找到https://stackoverflow.com/questions/11189688/linq-to-sql-updating-without-refresh-when-updatecheck-never,说在Linq设计器将表列设置上UpdateCheck = Never。我是直接编码的,不用设计器。通过在DEMO程序中添加一个Linq设计,发现些设置在代码中就是在Column属性中加一个UpdateCheck即可。

[Column(UpdateCheck = UpdateCheck.Never)]
public double? AField{get;set;}

然后分析为什么旧的数据为什么出现,而新数据不出现。在分析崩溃原因时先不进行UpdateCheck = Never的设置。发现所有可空字段没设置值在Where条件中都是Is NULL判断。但AField却是=判断,但数据库中却没有值(将实例类字段值全输出发现AFiled居然有值)。
这个问题原因就找到了,确实按照Where条件查询不到记录了,异常也发生了。
然后到Linq实体类中去找代码,如下(代码中相关属性设置没添加):

private double? _AField;
public double? AField{
    get{
        if (_AFiled == null) return BField;
        return _AFiled;
    }
}

终于找到了原因,当AFiled是NULL时,直接取BField的值了,程序中确实对BField赋值了。
然后发现出问题的数据都是在此代码提交之前产生的数据,提交之后产生的数据正常。
总结
Linq2SQL中,如果是计算列,不用持久化到数据库中。所以可以不用加Column这个Attribute。
Linq2SQL中,Update时默认会把所有的持久化字段(即添加了Column这个Attribute的字段)作为Where条件,如果是在发布后的程序中添加新的非主键字段,建议在Column中添加上UpdateCheck = UpdateCheck.Never,这样在发布后更新旧的数据不会发生这种莫名的异常。

目录
相关文章
|
3月前
|
设计模式 程序员
故意把代码写得很烂,这样的 “防御性编程“ 可取吗?
故意把代码写得很烂,这样的 “防御性编程“ 可取吗?
|
3月前
|
JavaScript 前端开发 UED
探秘 JavaScript 错误背后的真相——揭开异常类型的神秘面纱,让你的代码从此无懈可击!
【8月更文挑战第23天】本文深入探讨了JavaScript中常见的异常类型,包括`ReferenceError`(未定义的引用)、`TypeError`(类型错误)、`SyntaxError`(语法错误)、`RangeError`(范围错误)、`EvalError`(评估错误)以及`URIError`(URI错误),并通过示例展示了如何有效地诊断与处理这些异常。此外,还介绍了如何自定义错误类以适应特定场景的需求。掌握这些异常处理技巧对于构建稳定可靠的Web应用程序至关重要。
38 0
|
11月前
|
XML 开发框架 .NET
C# | Linq基本功 —— 必学的必熟的10个方法
Linq(Language Integrated Query)是C#语言中的一种查询语言,它提供了一种统一的方式来查询和操作各种数据源,如集合、数据库、XML等。Linq的出现使得开发者能够以一种更简洁、更直观的方式来处理数据,提高了代码的可读性和可维护性。
134 0
|
6月前
|
程序员 Python
救命!揭秘编程语言中被低估的神器——IF语句
救命!揭秘编程语言中被低估的神器——IF语句
38 2
|
开发者 Java 网络安全
消灭 Java 代码的“坏味道” | 开发者必读(078期)
最炫的技术新知、最热门的大咖公开课、最有趣的开发者活动、最实用的工具干货,就在《开发者必读》!
955 0
|
安全 中间件 PHP
clojure的web安全比你想象的还要差
ClojureWest大会结束了,Aaron Bedra发表了题为 Clojure.web/with-security的演说。如果你用Clojure开发web应用程序,你必须看这个视频。现在就看。 这篇博客综合了Aaron的讲话笔记和一些我自己的想法。
390 0
|
安全 架构师 程序员
资本家“坑”程序员的 15 个陷阱
要开发软件,你就需要程序员。程序员又贵、又懒、又难以掌控。不管他们开发的软件行不行,你都要付他们钱。不管怎样,对你来说,能少付他们一点是一点,毕竟钱不是大风刮来的。问题是,他们有时候会发现你给得太少,索性就不干了。那么,该怎样避免这种情况呢?
|
程序员
关于编程 鲜为人知的真相
导读:原文来自dotmac.rationalmind.net上一篇《Some lesser-known truths about programming》,译文来自外刊IT评论整理编译《关于编程,鲜为人知的真相》而来。
810 0
|
程序员 C++ Python
编程语言发明者们,结局都不太好,谁的错?
创造现在主流编程语言的程序员们,都怎么样了?提起灯泡的发明者,你可能想起亨利·戈培尔,提起印刷术,你可能会想到毕昇。这些伟人离我们太远太远,但当提起C++、python、java时,他们的发明者又离我们如此的近,至少他们还在世上,也在工作,但似乎他们的现状都不太好。
1684 0