SqlGeography未实现IComparable致DataSet.RejectChanges()失败,求解决方案
问题:DataSet.RejectChanges()因SqlGeography未实现IComparable抛出异常
开发基于SQL后端的企业级应用,使用C#的System.Data.DataSet等组件处理数据。此前将SqlGeography转换为DbGeography后存入DataTable一切正常,但发现部分浮点值往返转换时会出现微小精度误差(影响底层字节),因此改为全程保留SqlGeography类型。
大部分场景可正常工作,但调用dataSet.RejectChanges()时会抛出致命异常:
------------System.Data.DataException: Type 'Microsoft.SqlServer.Types.SqlGeography, Microsoft.SqlServer.Types, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' does not implement IComparable interface. Comparison cannot be done. at System.Data.Common.SqlUdtStorage.CompareValueTo(Int32 recordNo1, Object value)at System.Data.Index.CompareRecords(Int32 record1, Int32 record2) at System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append) at System.Data.Index.InitRecords(IFilter filter) at System.Data.DataTable.GetIndex(IndexField[] indexDesc, DataViewRowState recordStates, IFilter rowFilter) at System.Data.DataColumn.get_SortIndex() at System.Data.DataColumn.IsNotAllowDBNullViolated() at System.Data.DataSet.EnableConstraints() at System.Data.DataSet.set_EnforceConstraints(Boolean value) at System.Data.DataSet.RejectChanges() at CargoWise.EntityFramework.RowFactory.Rollback() in
原因分析
DbGeography此前能正常工作,是因为它不属于SQL类型(未实现INullable,参考System.Data.Common.DataStorage.CreateStorage),系统会创建ObjectStorage而非SqlUdtStorage。对于未实现IComparable的类型,ObjectStorage会通过ToString()做比较,这种方式足以满足IsNotAllowDBNullViolated()仅判断“是否为null”的需求(此前未因此出现问题)。但SqlUdtStorage在类型未实现IComparable时没有 fallback 机制,直接抛出异常。
现有方案的不足
目前考虑过几种方案,但都不够理想:
- 无法继承
internal sealed的SqlUdtStorage和SqlGeography - 为
SqlGeography编写轻量包装类实现IComparable - 通过反射为
SqlGeography类型的DataColumn赋值ObjectStorage - 将所有
SqlGeography列设为可空
这些方案都过于hacky,并非预期的解决方式。
请问是否有官方推荐方案?若无,最简洁的规避方法是什么?
内容的提问来源于stack exchange,提问作者Patashu
相关产品推荐
相关产品推荐

