Linq-to-Entities:LEFT OUTER JOIN与WHERE子句,计算和投影

时间:2013-06-23 01:58:32

标签: vb.net linq linq-to-entities

我很难搞清楚如何将多列上的简单SQL LEFT OUTER JOIN和where子句转换为工作的Linq-to-Entities查询。只有两张桌子。我需要Table1中所有行的值,无论Table2中的匹配如何,但是连接多个列证明是困难的。我还需要在查询中进行简单的计算,但也找不到。 SQL中的查询如下所示:

select t1.tableid1,
t1.tableid2,
t1.fieldvalue1,
t2.fieldvalue2,
isnull(t2.fieldvalue2,0) / t1.fieldvalue1 as calcvalue
t1.fieldvalue1 - isnull(t2.fieldvalue2,0) as calcvalue2
from table1 t1
left outer join table2 t2 
    on t1.tableid1 = t2.tableid1
    and t1.tableid2 = t2.tableid2
    and t1.tableid3 = t2.tableid3
where t1.tableid1 = @somevalue

我可以进行单列左连接,但我似乎找不到多列的正确语法,更不用说不知道如何在列上添加或减去值了。下面是我最好的猜测,但我得到了一个预期类型错误(在“新”之后和第一个左括号之前):

On New (t2.Field(Of String)("tableid1"), t2.Field(Of String)

最好的猜测:

Dim query = From t1 In dtTable1 _
                         Group Join t2 In dtTable2 _
                         On New (t2.Field(Of String)("tableid1"), t2.Field(Of String)("tableid2")) Equals _
                            (t1.Field(Of String)("tableid1"), t1.Field(Of String)("tableid2")) _
                         Into t2outer = Group _
                         From t2 In t2outer.DefaultIfEmpty() _
                         Select New With _
                        { _
                            .t1_tableid1 = t1.Field(Of String)("tableid1"), _
                            .t1_tableid2 = t1.Field(Of String)("tableid2"), _
                            .t1_fieldvalue1 = t1.Field(Of Integer)("fieldvalue1"))
                            .t2_fieldvalue2 = If(t2 Is Nothing, CType("0", Integer), t2.Field(Of Integer)("fieldvalue2"))
                        }

@Gert让我足够接近。我认为格式略有偏差,因为我必须添加括号而不是括号,并在“Key”关键字和id之间放置一个空格:

On New With {
                        Key .id1 = t2.Field(Of String)("tableid1"), _
                        Key .id2 = t2.Field(Of String)("tableid2")
                        } _
                    Equals _
                    New With {
                        Key .id1 = t1.Field(Of String)("tableid1"), _
                        Key .id2 = t1.Field(Of String)("tableid2")
                        } _

感谢Gert,我能够按照SQL查询中的描述进行操作。请参阅下面的SQL查询的完整工作表示:

Dim query = From t1 In dtTable1 _
    Where (T1.Field(Of String)("fieldvalue1") = SOMEVALUE) _
     Group Join t2 In dtTable2 _
     On New (t2.Field(Of String)("tableid1"), t2.Field(Of String)("tableid2")) Equals _
        (t1.Field(Of String)("tableid1"), t1.Field(Of String)("tableid2")) _
     Into t2outer = Group _
     From t2 In t2outer.DefaultIfEmpty() _
     Select New With _
    { _
        .t1_tableid1 = t1.Field(Of String)("tableid1"), _
        .t1_tableid2 = t1.Field(Of String)("tableid2"), _
        .t1_fieldvalue1 = t1.Field(Of Integer)("fieldvalue1"))
        .t2_fieldvalue2 = If(t2 Is Nothing, CType("0", Integer), t2.Field(Of Integer)("fieldvalue2"))
        .calcvalue = If(t2.Field(Of Integer)("fieldvalue2") Is Nothing, CType("0", Integer), t2.Field(Of Integer)("fieldvalue2")) _
            / CType(t1.Field(Of String)("fieldvalue1"), Integer), 
        .calcvalue2 = CType(t1.Field(Of String)("fieldvalue1"), Integer) _
            - If(t2.Field(Of Integer)("fieldvalue2") Is Nothing, CType("0", Integer), t2.Field(Of Integer)("fieldvalue2")) _
    }

2 个答案:

答案 0 :(得分:0)

对于实体,您有一个容器并按名称评估您的表。此where子句按字段值过滤结果,并且可以与更多值连接。 {}中的部分供您更改以匹配您的实体。此查询是IEnumerable(Of {your entity}) - 非常适合数据绑定。

Dim query = model.{table name}.Where(Function(o) o.{column name} = {some value}).ToList()

答案 1 :(得分:0)

首先,如果您对多个字段进行分组,则需要比较匿名类型,因此部分

On
   New (t2.Field(Of String)("tableid1"), t2.Field(Of String)("tableid2"))
Equals
       (t1.Field(Of String)("tableid1"), t1.Field(Of String)("tableid2"))

应更改为创建匿名类型的语法(与稍后在查询中使用的相同):

On
  New With {.id1 = t2.Field(Of String)("tableid1"),
            .id2 = t2.Field(Of String)("tableid2")}
Equals
  New With {.id1 = t1.Field(Of String)("tableid1"),
            .id2 = t1.Field(Of String)("tableid2")}

<强>但

在C#中这就足够了,因为对于匿名类型,C#编译器使用基于的相等性。但是出于某种原因,使用VB这是不同的,它使用引用相等。所以Equals总是false,因为第一个对象与第二个对象不是同一个对象。

幸运的是,VB具有Key关键字,可用于指示在比较匿名对象时要使用的属性。所以最终的语法是:

On
  New With {Key .id1 = t2.Field(Of String)("tableid1"),
            Key. id2 = t2.Field(Of String)("tableid2")}
Equals
  New With {Key .id1 = t1.Field(Of String)("tableid1"),
            Key .id2 = t1.Field(Of String)("tableid2")}