【问题标题】:"At least one object must implement IComparable" exception from LINQ query resultsLINQ 查询结果中的“至少一个对象必须实现 IComparable”异常
【发布时间】:2017-07-15 04:37:07
【问题描述】:

我没有非常广泛地使用 LINQ,但我正在尝试从大型 Excel 电子表格(14K+ 行)中读取数据,这需要我从多个工作表中进行查询,甚至重新查询原始电子表格以过滤特定数据。因为 Excel 的 OleDb 查询可能需要相对较长的时间(对于本地计算机上的文件,每次查询 500+ms),我在我的方法的前面执行了几个这样的查询,通过“基础”开始循环DataTable,然后尝试使用 LINQ 过滤该循环中的数据,以将适当的数据放入更结构化的 DataSet 中。这是一些帮助解释的代码(VB.NET):

Dim Connection As System.Data.OleDb.OleDbConnection
Dim Command As System.Data.OleDb.OleDbDataAdapter
Dim EXCEL_SHEET_DATA_1 As New DataTable
Dim EXCEL_SHEET_DATA_2 As New DataTable
Dim EXCEL_SHEET_DATA_3 As New DataTable
Dim TapeFile As New FileInfo("C:\TempFolder\tapefile.xls")

Connection = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0; Data Source='" & TapeFile.FullName & "'; Extended Properties=Excel 8.0;")
Command = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [SHEET1$] ORDER BY [USER_ID] ASC, [MEMBER_NUMBER] ASC;", Connection)
Command.Fill(EXCEL_SHEET_DATA_1)
Command.Dispose()

Command = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [SHEET2$] ORDER BY [USER_ID] ASC, [MEMBER_NUMBER] ASC;", Connection)
Command.Fill(EXCEL_SHEET_DATA_2)
Command.Dispose()

Command = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [SHEET3$] ORDER BY [USER_ID] ASC, [MEMBER_NUMBER] ASC;", Connection)
Command.Fill(EXCEL_SHEET_DATA_3)
Command.Dispose()

For Each Row As DataRow In EXCEL_SHEET_DATA_1.Rows
    Dim MemberNumber As String = Row("MEMBER_NUMBER").ToString.Trim
    Dim UserNumber As String = Row("USER_ID").ToString.Trim

' -- CODE FOR INITIAL PROCESSING OF SHEET1 DATA - NO ERRORS --

    Dim CoMemberQuery As IEnumerable(Of DataRow) = From cm In EXCEL_SHEET_DATA_2 Where cm("MEMBER_NUMBER") = MemberNumber And cm("USER_ID") = UserNumber

    For Each CoMemberRow As DataRow In CoMemberQuery

' -- CODE FOR PROCESSING OF SHEET2 DATA - NO ERRORS --

    Next CoMemberRow

    Dim VehicleQuery As IEnumerable(Of DataRow) = From veh In EXCEL_SHEET_DATA_1 Where veh("MEMBER_NUMBER") = MemberNumber And veh("USER_ID") = UserNumber Order By veh("VIN") Ascending

' *******************************************************
' -->> HERE IS WHERE I *SOMETIMES* GET THE EXCEPTION <<--
' *******************************************************
    For Each VehicleRow As DataRow In VehicleQuery
' -- CODE FOR SECONDARY PROCESSING OF SHEET1 DATA - NO ERRORS --
    Next VehicleRow
Next Row

我不是每次都遇到异常。我注意到的唯一可能与它有关的是,对于导致第一个异常的特定 MemberNumberUserNumber 组合,结果集中的第一行很可能包含 NULL 值VIN 字段。

我确定问题与我的 LINQ 查询语法有关,但我在这方面经验不足,不知道为什么会失败。任何帮助将不胜感激。如果您需要有关代码或实现的任何其他信息,请告诉我,我会尝试将其添加到问题中。 感谢您的宝贵时间。

【问题讨论】:

    标签: excel vb.net linq


    【解决方案1】:

    您的 VehicleQuery 包含以下短语:Order By veh("VIN") Ascending

    因此,一旦 VehicleQuery 被评估(通过启动 For 循环),LINQ 将评估该查询中的所有项目,然后执行排序操作,其中涉及将 veh("VIN") 值与每个其他并把它们整理好。

    当比较查询中的任何两个项目时,它会尝试查看其中一个值是否知道如何将自己与另一个类型的值进行比较(因此实现了IComparable 接口。如果他们不能,那么它不知道哪个一个应该先走。

    我的猜测是veh("VIN") (有时)会产生不知道如何将自己与此表达式返回的其他值进行比较的对象。根据您使用的数据类型以及您希望如何比较它,您可能会考虑进行某种类型的转换或转换,或者只是在值上调用ToString(),以确保它具有可比性:Order By veh("VIN").ToString() Ascending

    (请原谅任何语法错误,因为我是 C# 开发人员。)

    【讨论】:

    • 天哪!这似乎奏效了!太感谢了!考虑到它的简单性,我对自己没有提出这个解决方案感到有点不安,但它现在似乎运行没有错误。我担心它可能会阻止尝试将 NULL 值从 DataTable 转换为字符串,但它似乎已经通过整个 DataTables 组而没有任何进一步的错误(并且比我执行多个 OleDb 查询时快得多)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多