我试图弄清楚如何在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查询?
答案 0 :(得分: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 ,如果其中至少有一个有没有价值:
不,a = b
不仅仅是VB.NET中的一项任务。
运算符=
由编译器在赋值和比较之间自动切换。
此外,在 Quickwatch模式中,始终将其解析为比较。
C#的行为与VB不同:
刚刚检查过,在C#中,简单的==
操作数的行为就像你期望的那样(如 Ilya Ivanov 和 Konrad Morawski 在评论中的结果),所以在这个问题的场景中不需要使用HasValue 。
答案 1 :(得分:1)
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);