我正在尝试查询旧的Access数据库表,并将它们与SQL Server表进行比较。它们通常没有主键,或者它们有额外的字段,在90年代有一些用途,等等,或者新表有新字段,等等。
我需要根据运行时指定的一组字段来查找一个表中的记录,而不是另一个表。
因此,当我比较不同表中的数据时,我一直在SQL中进行这种查询:
dim fields_i_care_about as string = "field1, field2, field3"
'This kind of thing gets set by a caller, can be any number of fields, depends on the
'table
dim s as string= ""
dim flds = fields_i_care_about.split(",")
for i as integer = 0 to ubound(flds)
if s > "" then s += " AND "
s += " dysfunctional_database_table." & flds(i) & "=current_database_table." & flds(i)
next
s = "SELECT * from dysfunctional_database_table where not exists (SELECT * from current_database_table WHERE " & s & ")"
===
我尝试使用Linq来实现这一点,因为两种不同数据库类型的一些数据类型问题似乎不那么令人头疼,但我是林的新手,完全被卡住了。
我做到了:
将旧表和新表作为dt1和dt2 放入数据表中
Dim new_records = _ From new_recs In dt2.AsEnumerable Where Not ( _ From old_recs In dt1.AsEnumerable Where old_recs(field1) = new_recs(field1) AndAlso old_recs(field2) = new_recs(field2)).Any Select new_recs
但我不知道如何在飞行中加入这个部分——old_recs(field1)=new_recs
到目前为止,我已经尝试过:把我想比较的字段放在一个字符串中,然后把这个字符串作为一个变量(我想我可能作弊了,我想我作弊了)
dim str = old_recs(field1) = new_recs(field1) AndAlso old_recs(field2) = new_recs(field2)
From new_recs In dt2.AsEnumerable
Where Not ( _
From old_recs In dt1.AsEnumerable Where str).Any
Select new_recs
它告诉我它不能转换一个布尔-
如果没有Linq表达式,有什么方法可以做到这一点吗?它们似乎比我在这里要做的要复杂得多,而且它们需要大量的代码,而且我似乎找不到比较子查询中两个字段的表达式示例。
有没有更简单的方法?我知道我可以使用JOIN或IN来执行通常的EXISTS查询——在这种情况下,我不需要查询速度极快。而且我不需要使用DataTable或DataSet——我可以将数据放在其他类型的对象中。
所以我发现了很多使用MethodInfo和反射之类的示例代码,但我无法让它们发挥作用-这些Datarows有一个Field方法,但它需要在字段名参数之前添加一个(of object)参数,这很难做到。
所以我不确定这个解决方案是否是最有效的方法,但至少它有效。我很想知道这种方式是否有效,为什么或为什么不有效。似乎大多数人都用反思来做这类事情,但我无法让它正常工作,无论如何,我试图做的事情非常简单,而这些方法非常复杂。我想我是抱着SQL的心态来做Linq的,但不管怎样,它是有效的。
Dim f As Func(Of DataRow, DataRow, String, Boolean) = Function(d1 As DataRow, d2 As DataRow, s As String)
Dim fields = Split(s, ",")
Dim results As Boolean = True
For k As Integer = 0 To UBound(fields)
Dim obj = DataRowExtensions.Field(Of Object)(d1, fields(k))
Dim obj2 = DataRowExtensions.Field(Of Object)(d2, fields(k))
If obj <> obj2 Then results = False : Exit For
Next
Return results
End Function
Dim new_records = _
From new_recs In dt2.AsEnumerable.AsQueryable()
Where Not ( _
From old_recs In dt1.AsEnumerable.AsQueryable Where f(old_recs, new_recs, id_key)).Any
Select new_recs
Try
Return new_records.CopyToDataTable
Catch ex As Exception
Stop
End Try