6

我有以下 Linq lambda 表达式:

private IEnumerable<SubjectSelectorSubjectGroup> GetSubjectList()
{
    User user = db.Users.Find(WebSecurity.CurrentUserId);
    return db.RequiredSubjects.Where(r => !r.Subject.Name.Contains("Home"))
                              .GroupBy(r => r.Subject)
                              .OrderByDescending(r => r.Count())
                              .Select(r => new SubjectSelectorSubjectGroup()
                              {
                                  SubjectId = r.Key.SubjectId,
                                  SubjectName = r.Key.Name,
                                  IsInFavourites = HttpContext.Current.Request.IsAuthenticated &&
                                                  (user.Elective1 != null && user.Elective1.SubjectId == r.Key.SubjectId ||
                                                   user.Elective2 != null && user.Elective2.SubjectId == r.Key.SubjectId ||
                                                   user.Elective3 != null && user.Elective3.SubjectId == r.Key.SubjectId),
                                  Occurrences = r.Count()
                              });
}

当用户未登录时user,此函数中的变量为空。这应该不是问题,因为短路布尔评估应该处理这个问题。问题是,它没有!相反, aSystem.NullReferenceException被抛出。

当用户为 nullHttpContext.Current.Request.IsAuthenticated时返回 false。我通过注释掉引用user变量的括号部分来检查这一点,然后表达式正确计算。

有谁知道为什么在这种情况下实际上不需要时Linq to Sql尝试取消引用变量?user有没有人可以解决这个问题?

4

3 回答 3

5

整个表达式被转换为 SQL 并被评估为 SQL,这意味着&&运算符没有按预期短路。

您可以通过构建ElectiveX.SubjectId要搜索然后tmpList.Contains(r.Key.SubjectId)在查询中使用的列表或数组来解决问题。这将被翻译成一个WHERE IN (...)SQL 表达式。

于 2013-01-09T07:14:17.767 回答
3

这是我使用Anders Abel给出的建议解决这个问题的方法。

private IEnumerable<SubjectSelectorSubjectGroup> GetSubjectList()
{
    List<string> userSubjects = new List<string>();
    if (HttpContext.Current.Request.IsAuthenticated)
    {
        User user = db.Users.Find(WebSecurity.CurrentUserId);
        if (user.Elective1 != null) { userSubjects.Add(user.Elective1.SubjectId); }
        if (user.Elective2 != null) { userSubjects.Add(user.Elective2.SubjectId); }
        if (user.Elective3 != null) { userSubjects.Add(user.Elective3.SubjectId); }
    }

    return db.RequiredSubjects.Where(r => !r.Subject.Name.Contains("Home"))
                              .GroupBy(r => r.Subject)
                              .OrderByDescending(r => r.Count())
                              .Select(r => new SubjectSelectorSubjectGroup()
                              {
                                   SubjectId = r.Key.SubjectId,
                                   SubjectName = r.Key.Name,
                                   IsInFavourites = userSubjects.Contains(r.Key.SubjectId),
                                   Occurrences = r.Count()
                              });
}
于 2013-01-09T08:54:29.813 回答
1

我能想到这种行为的唯一原因是您的查询被转换为 SQL (因为它的 LINQ to SQL),并且user.Elective它正在尝试生成 CASE 语句。这就是您收到错误的原因。

于 2013-01-09T07:13:59.453 回答