1

我试图弄清楚如何在某些值可以为空的 LINQ 中进行查询。

接下来是我的桌子:

ID int
Key1 int
Key2 int?
Key3 int?
Value string

uniq = Key1+Key2+Key3+Value

现在我需要根据唯一约束检查​​现有记录是否已经存在。

我尝试了以下方法:

Object tmp = model.table.FirstOrDefault(row => row.Key1 == newItem.Key1 &&
             (row.Key2.HasValue && newItem.Key2.HasValue && row.Key2.Value == newItem.Key2.Value) &&
             (row.Key3.HasValue && newItem.Key3.HasValue && row.Key3.Value == newItem.Key3.Value) &&
             row.Value == newItem.Value);

和:

Object tmp = model.table.FirstOrDefault(row => row.Key1 == newItem.Key1 &&
             row.Key2 == newItem.Key2 &&
             row.Key3 == newItem.Key3 &&
             row.Value == newItem.Value);

但是当其中一个键为空时,两者都没有得到正确的结果!

有没有办法编写正确的 LINQ 查询?

4

2 回答 2

2
object tmp= model.table.FirstOrDefault(t => 
    t.Key1 == newItem.Key1 
    && ((!t.Key2.HasValue & !newItem.Key2.HasValue) 
        | t.Key2.Value == newItem.Key2.Value)                             
    && ((!t.Key3.HasValue & !newItem.Key3.HasValue) 
        | t.Key3.Value == newItem.Key3.Value) && t.Value == newItem.Value);
于 2013-01-16T11:54:48.717 回答
1

前段时间,我写了一个小函数来处理这些情况:

Private Function EqualOrBothNull(ByVal int1 As Int32?, ByVal int2 As Int32?) As Boolean
    Select Case True
        Case (int1 Is Nothing AndAlso int2 Is Nothing)
            Return True
        Case (int1 Is Nothing AndAlso int2 IsNot Nothing) OrElse (int1 IsNot Nothing AndAlso int2 Is Nothing)
            Return False
        Case (int1 IsNot Nothing AndAlso int2 IsNot Nothing)
            Return int1 = int2
    End Select
End Function

它在 VB.NET 中,但在 C# 中转换它应该很简单:

private bool EqualOrBothNull(Nullable<Int32> int1, Nullable<Int32> int2) {
    switch (true) {
        case (int1 == null && int2 == null):
            return true;
        case (int1 == null && int2 != null) || (int1 != null && int2 == null):
            return false;
        case (int1 != null && int2 != null):
            return int1 == int2;
    }
}

然后,您可以简单地编写:

Object tmp = model.table.FirstOrDefault(row =>
                      EqualOrBothNull(row.Key1, newItem.Key1) &&
                      EqualOrBothNull(row.Key2, newItem.Key2) &&
                      EqualOrBothNull(row.Key3, newItem.Key3) &&
                      EqualOrBothNull(row.Value, newItem.Value));

要回复对我的回答的几条评论:

至少在 VB.NET 中,两个 Nullable(Of T) 的比较总是计算为布尔值?如果其中至少一个没有值,则值为Nothing :

在此处输入图像描述

而 NO,a = b不仅仅是 VB.NET 中的一个作业。

运算符=由编译器在assignmentcomparison之间自动切换。

此外,在Quickwatch 模式下,它总是被解析为比较。

C# 的行为与 VB 不同:

刚刚检查过,在 C# 中,简单==操作数的行为就像您期望的那样(就像Ilya IvanovKonrad Morawski在评论中出现的那样),因此在这个问题的场景中不需要使用 HasValue 。

于 2013-01-16T11:47:09.560 回答