我正在进行下面的重复查询,其中'a'和'b'递增('b'递增到限制,然后重置和'a'递增)。可能有多行具有给定值'a'和'b'。
struct MyData {int mdA; int mydB; }
....
int find_next_a(int a, int b)
{
var q = from p in db.pos
where (p.a >= a && p.b > b) || (p.a > a && p.b > 0)
orderby p.a, p.b
select new MyData
{
mdA = p.a,
mdB = p.b
};
return q.First().mdA; // ERROR: InvalidOperationException at end of data
}
查询有效,直到我到达表的末尾。然后我得到异常InvalidOperationException。我不能调用q.Count()因为我得到了相同的异常。
如何检测q中没有有效数据?
[修改:] 谢谢 Jon Skeet (和Bojan Skrchevski,Bodrick),我将解决方案发布到上面。
int find_next_a(int a, int b)
{
var q = from p in db.pos
where (p.a >= a && p.b > b) || (p.a > a && p.b > 0)
orderby p.a, p.b
select new { p.a, p.b };
var result = q.FirstOrDefault(); // catch running past end of table
if (result == null)
return -1;
return q.First().a; // return real data
}
答案 0 :(得分:9)
您可以改为使用FirstOrDefault
:
var result = q.FirstOrDefault();
if (result == null)
{
// Query results were empty
}
请注意,在“实际结果是元素类型的默认值”和“无结果”之间无法区分......这里不是问题,因为所有实际结果都是非空引用,但值得注意的是。
编辑:我没有注意到你使用的是自定义结构;我把它误解为匿名类型。我强烈建议在这里使用匿名类型而不是可变结构。或者,假设您只需要mdA
,则可以使用:
var q = from p in db.pos
where (p.a >= a && p.b > b) || (p.a > a && p.b > 0)
orderby p.a, p.b
select (int?) p.a;
int? result = q.FirstOrDefault();
if (result == null)
{
// No results - take whatever action
}
else
{
// Got a result - find the underlying value...
int a = result.Value;
}
答案 1 :(得分:3)
而不是First()
使用FirstOrDefault()
,然后在使用之前检查null
值。
var rResult = q.FirstOrDefault();
if(rResult != null)
{
var something = rResult.mda;
}
答案 2 :(得分:2)
您可以使用FirstOrDefault()来避免InvalidOperationException。在以下示例中,如果q没有元素,则x将为null。然后,您可以检查并继续相应的操作。
var x = q.FirstOrDefault ();
return x == null ? -1 : x.mdA;