2017-07-14 14 views
1

LINQを非常に幅広く使用していませんが、複数のクエリを作成する必要がある大きなExcelスプレッドシート(​​14K +行)ワークシートを作成し、元のスプレッドシートを再クエリーして特定のデータをフィルタリングすることもできます。 ExcelのOleDbクエリは比較的長い時間がかかります(私のローカルマシン上のファイルに対してクエリごとに500 + ms)、私はメソッドの前でこれらのクエリを2回実行して、 "ベース"その後、LINQを使用してそのループ内のデータをフィルタリングし、適切なデータをより構造化されたDataSetに配置しようとします。ここでは説明するためのコードです(VB.NET):"少なくとも1つのオブジェクトはLINQクエリ結果からIComparableを実装する必要があります"

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の組み合わせの場合、結果セットの最初の行にはVINフィールドのNULL値が含まれている可能性が最も高いと気づいたことがあります。

私の問題はLINQのクエリ構文と関係していると思いますが、なぜこのように失敗したのかを知るにはあまりにも経験が足りません。どんな支援も大歓迎です。コードや実装に関する追加情報が必要な場合は、教えてください。質問に追加しようとします。 ありがとうございます。

答えて

3

あなたのVehicleQueryのフレーズはOrder By veh("VIN") Ascendingです。

だから、できるだけ早く(Forループを開始することで)評価されますVehicleQueryとして、LINQは、クエリ内のすべての項目を評価して、お互いにveh("VIN")値を比較し、それらを置く必要ソート操作を実行します注文。

クエリの2つの項目を比較すると、いずれかの値が他の型の値と比較する方法を知り(したがって、IComparableインターフェイスを実装しています。

私の推測では、veh("VIN")は、この式で返された他の値と比較する方法がわからない(時には)オブジェクトを生成することがあります。それを比較したい場合は、何らかのキャストやコンバージョンを実行するか、値にToString()を単に呼び出して比較してみてください:Order By veh("VIN").ToString() Ascending

(私はC#デベロッパーなので、文法上の誤りはご容赦ください。)

+1

聖なるものです!それはうまくいったようです!どうもありがとうございます!私は、単純なことを考えれば、自分自身で解決策を思い付いていないため、ちょっと気になりますが、今はエラーなく実行されているようです。私はそれがDataTableからStringsにNULL値をキャストしようとしているのを恐れているかもしれないと懸念していましたが、それ以上のエラーなしで(そして複数のOleDbクエリを実行していたときよりもずっと速い) –

関連する問題