如何在VB.NET中将DataTable转换为自定义类对象并实现数据对比
转换逻辑实现方案
直接用CType(dt1, ISAACService)报错的核心原因是:DataTable是多行数据的集合类型,和ISAACService单条实体类型不存在任何继承、实现关系,也没有自定义的类型转换规则,无法直接强制转换。你需要手动编写映射逻辑,把DataTable里的每一行数据转换成对应的ISAACService实例。
第一步:完善ISAACService类实现
你需要确保ISAACService继承自ISAACServiceBase并正确实现构造函数:
Public Class ISAACService Inherits ISAACServiceBase Implements IComparable(Of ISAACService) ' 调用基类构造函数传递参数 Public Sub New(kArt As String, uNR As String, üBegriff As String, bnung As String, anzl As Double, enht As String, eKosten As Double, gMenge As Integer, zz As String) MyBase.New(kArt, uNR, üBegriff, bnung, anzl, enht, eKosten, gMenge, zz) End Sub ' 你已有的CompareTo逻辑可以保留,也可以自行扩展其他字段的对比规则 Public Function CompareTo(other As ISAACService) As Integer Implements IComparable(Of ISAACService).CompareTo If other Is Nothing Then Return 1 Return String.Compare(Me.UANR, other.UANR) End Function End Class
第二步:编写DataTable转ISAACService集合的通用方法
该方法会遍历DataTable的每一行,按列映射生成ISAACService实例,注意替换代码中的列名为你实际DataTable中的列名:
Private Function ConvertDataTableToISAACList(dt As DataTable) As List(Of ISAACService) Dim resultList As New List(Of ISAACService) If dt Is Nothing OrElse dt.Rows.Count = 0 Then Return resultList For Each row As DataRow In dt.Rows ' 如有空值判断需求,可先调用row.IsNull("列名")做兼容处理 Dim serviceItem As New ISAACService( kArt:=row("KostenArt").ToString(), uNR:=row("UANR").ToString(), üBegriff:=row("Überbegriff").ToString(), bnung:=row("Benennung").ToString(), anzl:=Convert.ToDouble(row("Anzahl")), enht:=row("Einheit").ToString(), eKosten:=Convert.ToDouble(row("Einzelkosten")), gMenge:=Convert.ToInt32(row("Gesamtmenge")), zz:=row("Z").ToString() ) resultList.Add(serviceItem) Next Return resultList End Function
第三步:修改对比逻辑,支持结果存入绑定列表
你可以自定义对比结果类,用BindingList存储结果方便直接绑定到控件展示:
' 对比结果实体类,可根据需求扩展字段 Public Class CompareResult Public Property UANR As String Public Property Status As String Public Property LeftItem As ISAACService Public Property RightItem As ISAACService End Class ' 绑定列表可直接赋值给DataGridView的DataSource属性 Public resultBindingList As New BindingList(Of CompareResult) Private Sub CompareDataTables() ' 先把两个DataTable转换为实体集合 Dim isaacList1 = ConvertDataTableToISAACList(dt1) Dim isaacList2 = ConvertDataTableToISAACList(dt2) resultBindingList.Clear() ' 取两个集合所有的UANR做全量对比,避免行顺序不一致导致的对比错误 Dim allUANR = isaacList1.Select(Function(x) x.UANR).Union(isaacList2.Select(Function(x) x.UANR)).Distinct() For Each uanr In allUANR Dim leftItem = isaacList1.FirstOrDefault(Function(x) x.UANR = uanr) Dim rightItem = isaacList2.FirstOrDefault(Function(x) x.UANR = uanr) Dim res As New CompareResult With { .UANR = uanr, .LeftItem = leftItem, .RightItem = rightItem } If leftItem IsNot Nothing AndAlso rightItem IsNot Nothing Then res.Status = If(leftItem.CompareTo(rightItem) = 0, "数据一致", "字段存在差异") ElseIf leftItem IsNot Nothing res.Status = "仅左表存在" Else res.Status = "仅右表存在" End If resultBindingList.Add(res) Next End Sub
注意事项
- 若DataTable中的列名和
ISAACServiceBase的属性名不一致,需要把映射代码中的列名替换为实际列名 - 如果数据中可能存在空值,需要在转换前先判断
row.IsNull("列名"),给属性赋默认值避免转换报错 - 现有
CompareTo仅对比了UANR字段,如果需要对比其他属性,自行扩展对比逻辑即可
内容的提问来源于stack exchange,提问作者idontgetit
相关产品推荐
相关产品推荐

