以进一步的规定重新审视上一个问题......
任何人都知道如何执行以下操作,忽略案例?
Dim Matches = From mRows In LinqMasterTable Join sRows In LinqSecondTable _
On mRows(ThePrimaryKey) Equals sRows(TheForignKey) _
Order By mRows(ThePrimaryKey) _
Select mRows, sRows
有关查询及其功能/用法的详细信息,上一篇文章为here。
修改
以下是我们查询的表格类型:
LinqMasterTable:
-------------------------------------
|ThePrimaryKey| Description |
-------------------------------------
|Green | This is a Green apple |
|GREEN | This is a Green apple |
|green | This is a Green apple |
|Red | This is a Red apple |
|RED | This is a Red apple |
|red | This is a Red apple |
-------------------------------------
LinqSecondTable
--------------------------
|TheForignKey | ApplePrice |
--------------------------
|Green | $0.90 |
|Pink | $0.80 |
|Red | $0.85 |
|Yellow | $0.79 |
--------------------------
这是理想的结果:
--------------------------------------
|Green | This is a Green apple | $0.90 |
|GREEN | This is a Green apple | $0.90 |
|green | This is a Green apple | $0.90 |
|Red | This is a Red apple | $0.85 |
|RED | This is a Red apple | $0.85 |
|red | This is a Red apple | $0.85 |
--------------------------------------
不幸的是,实际(不受欢迎的)结果是:
--------------------------------------
|Green | This is a Green apple | $0.90 |
|Red | This is a Red apple | $0.85 |
--------------------------------------
ReEdit:
Private Sub LinqTwoTableInnerJoinCaseInsensitive(ByRef qMasterDS As DataSet, _
ByRef qMasterTable As DataTable, _
ByRef qSecondDS As DataSet, _
ByRef qSecondTable As DataTable, _
ByRef qPrimaryKey As String, _
ByRef qForignKey As String, _
ByVal qResultsName As String)
Dim TheMasterTable As String = qMasterTable.TableName 'Table Name'
Dim TheSecondTable As String = qSecondTable.TableName 'Table Name'
Dim ThePrimaryKey As String = qPrimaryKey 'The variable name of the first 'merge on' column'
Dim TheForignKey As String = qForignKey 'The variable name of the second 'merge on' column'
Dim TheNewForignKey As String = "" 'For handling duplicate column names'
MasterTableColumns = GetColumns(qMasterDS, TheMasterTable)
SecondTableColumns = GetColumns(qSecondDS, TheSecondTable)
Dim mColumnCount As Integer = MasterTableColumns.Count
Dim sColumnCount As Integer = SecondTableColumns.Count
Dim ColumnCount As Integer = mColumnCount + sColumnCount
Dim LinqMasterTable = qMasterDS.Tables(TheMasterTable).AsEnumerable
Dim LinqSecondTable = qSecondDS.Tables(TheSecondTable).AsEnumerable
'Original LINQ Query: (Works, but is case sensitive)'
Dim Matches = From mRows In LinqMasterTable Join sRows In LinqSecondTable _
On mRows(ThePrimaryKey) Equals sRows(TheForignKey) _
Order By mRows(ThePrimaryKey) _
Select mRows, sRows
'IntelliSense doesnt see "ToUpper" as available. No errors, but no search results.'
'Error: Public member "ToUpper" on type "DBNull" not found.'
'Dim Matches = From mRows In LinqMasterTable Join sRows In LinqSecondTable _'
' On mRows(ThePrimaryKey).ToUpper Equals sRows(TheForignKey).ToUpper _'
' Order By mRows(ThePrimaryKey) _'
' Select mRows, sRows'
'Message = "Public member "sRows" on type "String" not found."'
'Dim Matches2 = From mRows In LinqMasterTable _'
'From sRows In LinqSecondTable _'
'Where String.Equals(mRows(ThePrimaryKey), sRows(TheForignKey), StringComparison.OrdinalIgnoreCase) _'
'Select mRows, sRows'
'Conversion from type "DBNull" to type "String" is not valid.'
'Dim Matches = _'
'LinqMasterTable.AsEnumerable().Join( _'
'LinqSecondTable.AsEnumerable(), _'
'Function(mRows) mRows("ThePrimaryKey"), _'
'Function(sRows) sRows("TheForignKey"), _'
'Function(mRows As DataRow, sRows As DataRow) New With {mRows, sRows}, _'
'StringComparer.InvariantCultureIgnoreCase)'
'Doesnt work at all - multiple errors'
'Dim Matches2 = _'
'LinqMasterTable _'
' .Join( _'
' LinqSecondTable, _'
' Function(x) x.Key.ToLower(), _'
' Function(x) x.Key.ToLower(), _'
' Function(o, i) New With {.ID = o.Key, .Description = o.Value, .Price = i.Value} _'
' ).Dump()'
' Make sure the dataset is available and/or cleared:'
If dsResults.Tables(qResultsName) Is Nothing Then dsResults.Tables.Add(qResultsName)
dsResults.Tables(qResultsName).Clear() : dsResults.Tables(qResultsName).Columns.Clear()
'Adds Master Table Column Names'
For x = 0 To MasterTableColumns.Count - 1
dsResults.Tables(qResultsName).Columns.Add(MasterTableColumns(x))
Next
'Rename Second Table Names if Needed:'
For x = 0 To SecondTableColumns.Count - 1
With dsResults.Tables(qResultsName)
For y = 0 To .Columns.Count - 1
If SecondTableColumns(x) = .Columns(y).ColumnName Then
SecondTableColumns(x) = SecondTableColumns(x) & "_2"
End If
Next
End With
Next
'Make sure that the Forign Key is a Unique Value'
If ForignKey1 = PrimaryKey Then
TheNewForignKey = ForignKey1 & "_2"
Else
TheNewForignKey = ForignKey1
End If
'Adds Second Table Column Names'
For x = 0 To SecondTableColumns.Count - 1 'Need error handling for if columnname exists'
dsResults.Tables(qResultsName).Columns.Add(SecondTableColumns(x))
Next
PleaseWait(True) 'Locks controls while processing data'
'Copy Results into the Dataset:'
For Each Match In Matches
'Build an array for each row:'
Dim NewRow(ColumnCount - 1) As Object
'Add the mRow Items:'
For x = 0 To MasterTableColumns.Count - 1
NewRow(x) = Match.mRows.Item(x)
Next
'Add the srow Items:'
For x = 0 To SecondTableColumns.Count - 1
Dim y As Integer = x + (MasterTableColumns.Count)
NewRow(y) = Match.sRows.Item(x)
Next
'Add the array to dsResults as a Row:'
dsResults.Tables(qResultsName).Rows.Add(NewRow)
Next
If chkUnique.Checked = True Then
ReMoveDuplicates(dsResults.Tables(qResultsName), ThePrimaryKey)
End If
PleaseWait(False) 'Unlocks controls after processing data'
If Not chkRetainKeys.Checked = True Then 'Removes Forign Key'
dsResults.Tables(qResultsName).Columns.Remove(TheNewForignKey)
End If
'Clear Arrays'
MasterTableColumns.Clear()
SecondTableColumns.Clear()
End Sub
顺便提一下,还有一些其他信息:
Dim MasterTableColumns As New ArrayList() 'Holds the Names of the Master Table Columns'
Dim SecondTableColumns As New ArrayList() 'Holds the Names of the Second Table Columns'
Dim MasterTable As String 'Current User Selected Master Table'
Dim PrimaryKey As String 'Table 0 User Selected Key'
Dim ForignKey1 As String 'Table 1 User Selected Key'
Private Function GetColumns(ByVal aDataset As DataSet, ByVal aTable As String) As ArrayList
If aDataset Is Nothing Then Return Nothing
If Not aDataset.Tables(aTable) Is Nothing Then
Dim TempArray As New ArrayList()
For x = 0 To aDataset.Tables(aTable).Columns.Count - 1
With aDataset.Tables(aTable).Columns(x)
TempArray.Add(.ColumnName)
End With
Next
Return TempArray
Else
MsgBox("There are no column names in the table """ & aTable & """ to load.")
Return Nothing
End If
End Function
答案 0 :(得分:0)
您需要在联接中指定IEqualityComparer<T>
,但不能使用查询语法来执行此操作。您必须使用扩展方法语法:
Dim Matches = _
LinqMasterTable.AsEnumerable().Join( _
LinqSecondTable.AsEnumerable(), _
Function(mRows) mRows("ThePrimaryKey"), _
Function(sRows) sRows("TheForeignKey"), _
Function(mRows As DataRow, sRows As DataRow) New With { mRows, sRows }, _
StringComparer.InvariantCultureIgnoreCase)
答案 1 :(得分:0)
以下是另一种可能的解决方案:加入小写版本的密钥:
LinqMasterTable _
.Join( _
LinqSecondTable, _
Function(x) x.ThePrimaryKey.ToLower(), _
Function(x) x.TheForignKey.ToLower(), _
Function(o,i) New With { .ID = o.ThePrimaryKey, .Description = o.Description, .Price = i.ApplePrice } _
)
使用您的样本数据进行测试可提供您所需的确切结果:
LinqPad测试(VB版):
Dim LinqMasterTable = New Dictionary(Of String, String)()
LinqMasterTable.Add("Green", "This is a Green apple")
LinqMasterTable.Add("GREEN", "This is a Green apple")
LinqMasterTable.Add("green", "This is a Green apple")
LinqMasterTable.Add("Red", "This is a Red apple")
LinqMasterTable.Add("RED", "This is a Red apple")
LinqMasterTable.Add("red", "This is a Red apple")
Dim LinqSecondTable = New Dictionary(Of String, String)()
LinqSecondTable.Add("Green", "$0.90")
LinqSecondTable.Add("Pink", "$0.80")
LinqSecondTable.Add("Red", "$0.85")
LinqSecondTable.Add("Yellow", "$0.79")
LinqMasterTable _
.Join( _
LinqSecondTable, _
Function(x) x.Key.ToLower(), _
Function(x) x.Key.ToLower(), _
Function(o,i) New With { .ID = o.Key, .Description = o.Value, .Price = i.Value } _
).Dump()
返回:
ID Description Price
Green This is a Green apple $0.90
GREEN This is a Green apple $0.90
green This is a Green apple $0.90
Red This is a Red apple $0.85
RED This is a Red apple $0.85
red This is a Red apple $0.85
(我在C#中编写并测试过,所以让我知道如果把它转换成VB就搞砸了!)
原创C#:
LinqMasterTable
.Join(
LinqSecondTable,
x => x.ThePrimaryKey.ToLower(),
x => x.TheForignKey.ToLower(),
(o,i) => new { ID = o.ThePrimaryKey, Description = o.Description, Price = i.ApplePrice }
)
答案 2 :(得分:0)
我们可以提出的最佳解决方案:
[1]将XLS File1导入数据集ds1和XLS File2导入数据集ds2
[2]允许用户选择所需的合并使用列
[3]将UPPER列添加到ds1和ds2
[4]将两列表的列数据复制为大写:
For each dr as DataRow in ds1.Tables(0).Rows
dr.Item(UPPER) = dr.Item(MixCaps).ToUpper
Next
[5]使用UPPER列合并表格
[6]删除UPPER列并输出合并表
我知道这个输出并不严格使用LINQ to Merge Case Insensitively,但它是我在截止日期内可以做的最好的。感谢所有帮助人员。希望其他想法能够奏效。咩。也许下次。
韦恩派对。 加思派对。