6

次のLinqラムダ式があります:

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、この関数の変数は null です。これは、短絡ブール値の評価で対処する必要があるため、問題にはなりません。問題は、そうではないということです。代わりに、 aSystem.NullReferenceExceptionがスローされます。

ユーザーが null の場合はHttpContext.Current.Request.IsAuthenticatedfalse を返します。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.ElectiveCASE ステートメントを生成しようとしているからです。そのため、エラーが発生しています。

于 2013-01-09T07:13:59.453 に答える