为了解决当列值为空时导致StrongTypingExceptions的ADO.Net数据集的臭名昭着的限制,我尝试根据this comprehensive blog post中名为Suncat的用户的建议拼凑一个解决方案。该解决方案又基于Danila Korablin's sample C# code in this deleted Microsoft Connect thread。当将null值传递到与数据集中的每个列关联的Property Get和Set语句时,会发生强类型异常;问题在于,微软将StrongTypingExceptions直接添加到数据集设计器生成的代码中,这使得.Net用户在过去十年中一无所有,包括那些仍在维护旧代码的人。 Suncat和Korablin的方法是创建新的代理属性,允许拥有这些列的DataRows的Partial Class语句中的空值。这种解决方法的缺点是它使DataRow定义与那些列的可以为空的双打混乱,所以我试图通过简单地继承数据集并将其替换的Nullable列声明为Shadows来改进它,以便隐藏StrongTypingExceptions抛出原始属性定义。我遇到的问题是我的Shadows属性似乎被忽略了;除非我完全删除设计师的原始属性声明,否则它们永远不会被调用。
在下面的示例代码中,表名是ConnectionTable,列/属性名为MyRate,我的原始设计器生成的数据集是ProjectsDataSet,它由名为InheritingDataSet的新数据集继承。如果我将一个WPF数据网格或其他任何内容绑定到一个连接到InheritingDataSet而不是它的基础的CollectionViewSource,那么所有内容都可以正常加载 - 直到我在代码中调用一个强类型属性,在这种情况下调用原始数据集的属性版本,以及空值的违规异常处理程序。我的可以为空的Shadows版本永远不会被调用,除非我手动删除原始设计器生成的版本,我觉得很奇怪。
这是原始设计器生成的属性代码:
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")> _
Public Property MyRate() As Long
Get
Try
Return CType(Me(Me.tableConnectionTable.MyRateColumn), Object)
Catch e As Global.System.InvalidCastException
Throw New Global.System.Data.StrongTypingException("The value for column 'MyRate' in table 'ConnectionTable' is DBNul" & _
"l.", e)
End Try
End Get
Set(value As Long)
Me(Me.tableConnectionTable.MyRateColumn) = value
End Set
End Property
这是我继承原文的代码。 GetProperty和SetProperty函数只是帮助类,旨在减少我需要编写的代码量,如果我最终需要数百个这样的阴影可空属性;如果我拿出来,结果是一样的。
Partial Public Class InheritingDataSet
Inherits ProjectsDataSet
Partial Public Shadows Class ConnectionTableRow
Private InternalMyRate As Double
Public Shadows Property MyRate() As Double?
Get
Return GetProperty(InternalMyRate)
End Get
Set(value As Double?)
InternalMyRate = value
End Set
End Property
End Class
Public Shared Function GetProperty(value)
If value Is Nothing OrElse NullCheck(value) = True Then
Return Nothing
Else
Return value
End If
End Function
Public Shared Function SetProperty(value)
If value Is Nothing Then
Return Global.System.Convert.DBNull
Else
Return value
End If
End Function
End Class
我不经常使用继承,所以我可能在我的声明中做错了。我已经尝试从ConnectionTableRow声明中删除Shadows关键字,以及遮蔽父表,但无济于事。有趣的是,如果我将Shadows更改为Overrides,编译器会给出一个错误,指出我的属性“无法声明'覆盖',因为它不会覆盖基类中的属性。”我无法理解为什么编译器显然无法在基础数据集中找到该属性。我还注意到,由于某种原因,我与InheritingDataset一起使用的CollectionViewSources的Source属性(所有这些都完全在XAML中完成)将其Dataset属性设置为InheritingDataset,但奇怪的是,与CollectionVieWsource关联的DataTable上的Dataset属性视图由于某种原因默认为ProjectsDataSet。有没有人对如何使这项工作有任何建议?在这些年之后,确实没有针对StrongTypingException问题的任何好的,简洁的解决方案,所以如果我能够实现这一点,那么对于仍然维护这些旧.Net数据集的许多人来说这可能是有益的。提前谢谢。