使用子查询中的动态字段将两表存在查询从 SQL 转换为 Linq

发布于 2024-11-14 01:42:26 字数 1862 浏览 2 评论 0原文

我正在尝试查询旧的 Access 数据库表并将它们与 SQL Server 表进行比较。 它们通常没有主键,或者它们具有在九十年代具有某种用途的额外字段等,或者新表具有新字段等。

我需要查找记录 - 基于运行时指定的一组字段- 它们在一张表中,但不在另一张表中。

因此,当我比较不同表中的数据时,我总是在 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 执行此操作,因为这似乎是两个不同数据库的一些数据类型问题类型变得不那么令人头痛, 但我是 Linq 的新手,完全陷入困境。

我得到了这样的结果:

  • 将旧表和新表放入数据表中作为 dt1 和 dt2

     Dim new_records = _
                来自 new_recs 中的 dt2.AsEnumerable
                哪里不 (_
                    来自 old_recs 在 dt1.AsEnumerable 其中 old_recs(field1) = new_recs(field1) AndAlso old_recs(field2) = new_recs(field2)).Any
                 选择新记录
    

但我不知道如何动态地将这部分放入 - old_recs(field1) = new_recs(field1) 还有 old_recs(field2) = new_recs(field2)

到目前为止我已经尝试过: 将我想要比较的字段放入字符串中,然后将该字符串作为变量放入(我以为我可能在作弊,我想我是)

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 - 我可以将数据放入其他类型的对象中。

I'm trying to query old Access database tables and compare them with SQL Server tables.
They often don't have primary keys, or they have extra fields that had some purpose in the nineties, etc., or the new tables have new fields, etc.

I need to find records - based on a set of fields specified at runtime - that are in one table but not another.

So, I do this kind of query all the time in SQL, when I'm comparing data in different tables:

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 & ")"

====

I'm trying to do this using Linq because it seems like some of the datatype problems with two different database types become less of a headache,
but I'm new to Linq and totally stuck.

I got as far as this:

  • Put old and new tables into datatables as dt1 and 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
    

But I can't figure out how to put this part in on the fly -
old_recs(field1) = new_recs(field1) AndAlso old_recs(field2) = new_recs(field2)

So far I've tried:
putting the fields I want to compare and making them a string and just putting that string in as a variable ( I thought I was probably cheating, and I guess I was)

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

It tells me it can't convert a Boolean -

Is there any way to do this without Linq expressions? They seem far more complex than what I'm trying to do here, and they take a lot of code, and also I can't seem to find examples of Expressions where we're comparing two fields in a subquery.

Is there a simpler way? I know I could do the usual EXISTS query using JOIN or IN - in this case I don't need the query to be super fast or anything. And I don't need to use a DataTable or DataSet - I can put the data in some other kind of object.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怪异←思 2024-11-21 01:42:26

所以我找到了很多使用 MethodInfo 和反射之类的示例代码,但我无法让其中任何一个工作 - 这些 Datarows 有一个 Field 方法,但它要求您在之前添加一个(对象)参数字段名称参数,这很难做到。

所以我不确定这个解决方案是否是最有效的方法,但至少它有效。我有兴趣了解这种方法是否有效以及为什么或为什么不有效。似乎大多数人都使用反射来做这种事情,但我无法让它正常工作,无论如何我想做的事情非常简单,而这些方法非常复杂。我想我是用 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

So I found a lot of sample code that used MethodInfo and reflection and things like that, but I couldn't get any of it to work - these Datarows have a Field method but it requires that you add an (of object) argument before the field name argument and that's tricky to do.

So I'm not sure if this solution is the most efficient way, but at least it works. I'd be interested in finding out whether this way of doing it is efficient and why or why not. It seemed like most people used reflection to do this kind of thing, but I couldn't get that working properly and anyway what I'm trying to do is pretty simple while those methods were pretty complex. I suppose I'm doing Linq with a SQL mindset, but anyway it works.

 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文