1

我对以下代码有一个奇怪的问题:

!isActive.HasValue || (isActive.HasValue && x.IsActive == isActive.Value)

isActive是一个bool?类型,所以如果isActivenull,那么我会得到以下错误:

可空对象必须有一个值。

有什么想法吗?谢谢你的帮助!

更新1:

public static List<User> Select(int userId, bool? isActive = null)
{
    var dl = DataLayer.GetDataContext();
    return dl.Users.Where(x => x.ID == userId
                && (!isActive.HasValue || (isActive.HasValue && x.IsActive == isActive.Value))).ToList();
}

这是我收到此错误的示例函数。我知道这很奇怪!如果我像下面这样更改,它将起作用:

!isActive.HasValue || (isActive.HasValue && x.IsActive == isActive)

我理解这个错误的意思,但我不明白为什么。我认为它应该有效。所以我称之为奇怪的东西!

更新 2:

  1. x.IsActive 是 bool 类型,而不是 bool?。我确信它:)
  2. DataLayer.GetDataContext() 用于 Linq to SQL。

可能是因为我使用的是 SQL Server 吗?

谢谢你们到目前为止的帮助。

4

6 回答 6

1

您的代码中有两个不同isActive的值,因此看起来您在x第二次检查中遗漏了:

!isActive.HasValue || (x.isActive.HasValue && (x.IsActive == isActive.Value))
                   ----^

我还在相等检查周围添加了括号,以消除对顺序或操作的任何混淆

于 2013-05-01T15:41:39.320 回答
1

由于它是 Linq-to-SQL,那么它可能不是短路或以正确的顺序评估表达式部分。我没有使用过它,但据我了解,它会读取您的 lambda 表达式的内容并将其转换为等效的 SQL 语句;它实际上并不像 C# 代码那样执行它。

即便如此,当值固定时,对每个项目进行检查似乎有点多。您可以这样重写该方法:

public static List<User> Select(int userId, bool? isActive = null)
{
    var dl = DataLayer.GetDataContext();
    var users = dl.Users.Where(x => x.ID == userID);

    if (!isActive.HasValue)
    {
        return users.ToList();
    }
    else
    {
        bool isActiveValue = isActive.Value;
        return users.Where(x => x.IsActive == isActiveValue).ToList();
    }
}

这样,如果生成的 SQL 查询不适用,就没有额外的约束。编辑:另外更新了它,没有任何可以为空的布尔值传递到您的查询中。

于 2013-05-01T16:16:12.157 回答
1

哦,这是因为 LINQ 中的查询生成器。可能有一种方法可以在一个查询中执行您的意图(实际上,听起来您在 q 中更新的代码就是这样做的),但最简单的做法是将其拆分为两个查询,因为您isActive事先知道 的值。这样您就不必担心查询构建器可能会或可能不会做什么。

就此而言,您不妨将这两个单独的函数完全分开,只是为了让未来的维护者更难意外落入同一个陷阱:

public static List<User> Select(int userId)
{
    return DataLayer.GetDataContext().Users.Where(x => x.ID == userId).ToList();
}

public static List<User> Select(int userId, bool isActive)
{
    return DataLayer.GetDataContext().Users.Where(x => x.ID == userId && x.IsActive == isActive).ToList();
}
于 2013-05-01T16:40:21.287 回答
0

你的代码不应该在那条线上失败。

我猜它在你的if街区的某个地方失败了(我假设这就是这个声明的目的)。isActive如果is ,您的第一个条件将返回 true null。如果您随后尝试在块内使用 isActive,您将收到 Nullable 错误。

于 2013-05-01T15:37:15.097 回答
0

如果你这样做,代码在哪里失败?

public static List<User> Select(int userId, bool? isActive = null)
{
    var dl = DataLayer.GetDataContext();
    return dl.Users.Where(x => E(userId, isActive, x)).ToList();
}

static bool E(int userId, bool? isActive, User x)
{
    return x.ID == userId && D(isActive, x);
}

static bool D(bool? isActive, User x)
{
    return (!isActive.HasValue || C(isActive, x));
}

static bool C(bool? isActive, User x)
{
    return (isActive.HasValue && B(isActive, x));
}

static bool B(bool? isActive, User x)
{
    return x.IsActive == isActive.Value;
}
于 2013-05-01T16:16:18.133 回答
-3

将其类型从 bool 更改为 bool?

bool? IsActive = false;
于 2013-05-01T15:38:32.763 回答