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,这样在发布后更新旧的数据不会发生这种莫名的异常。

目录
相关文章
|
编译器 C语言
C语言编程陷阱:移植性
在编写可移植的C代码时,我们应考虑和应对可移植性缺陷,以确保代码能够在不同平台上正确运行。通过遵循C语言标准、了解特定平台的行为和使用标准库提供的函数等手段,可以减少可移植性问题的发生,并编写出更加健壮和可靠的C代码。同时,积极参与C语言社区和了解最新的C语言标准变化也是确保代码可移植性的重要方式。
147 0
|
自然语言处理 编译器 C语言
C语言编程陷阱:词法陷阱
推荐一个零声学院免费教程,个人觉得老师讲得不错, 服务器课程
49 0
|
编译器 C语言
C语言编程陷阱:语法陷阱
c语言要求在函数调用时即使函数不带参数,也应该包括函数列表。 是挂else问题
71 0
|
5月前
|
设计模式 程序员
故意把代码写得很烂,这样的 “防御性编程“ 可取吗?
故意把代码写得很烂,这样的 “防御性编程“ 可取吗?
|
XML 开发框架 .NET
C# | Linq基本功 —— 必学的必熟的10个方法
Linq(Language Integrated Query)是C#语言中的一种查询语言,它提供了一种统一的方式来查询和操作各种数据源,如集合、数据库、XML等。Linq的出现使得开发者能够以一种更简洁、更直观的方式来处理数据,提高了代码的可读性和可维护性。
152 0
|
8月前
|
Java Unix C语言
在我掉入计算机的大坑并深陷其中时,一门名为“C语言”的编程语言让我沉迷
在我掉入计算机的大坑并深陷其中时,一门名为“C语言”的编程语言让我沉迷
|
缓存 小程序 Java
IntegerCache的妙用和陷阱!
考虑下面的小程序,你认为会输出为什么结果?
130 0
IntegerCache的妙用和陷阱!
程序人生 - 箴言
程序人生 - 箴言
89 0
|
存储 Java API
java编程思想第四版第十一章总结
容器类被分为两类:Collection和Map
116 0
|
Java 程序员
java编程思想第四版第六章总结
为什么f要代码重构 第一次代码不一定是完美的, 总会发现更优雅的写法.
180 0