0

私は次のモデルを持っています(この質問のために唖然としました):

public class Student
{
    public int ID { get; set; }
    public virtual ICollection<StudentCourse> StudentCourses { get; set; }

     public Student(){
        StudentCourses = new List<StudentCourse>();
    }
}

public class StudentCourse
{
    public int ID { get; set; }
    public string Grade { get; set; }
    public int StudentID { get; set; }
    public int CourseID { get; set; }

    public virtual Student Student { get; set; }
    public virtual Course Course { get; set; }
}

public class Course
{
    public int ID { get; set; }        
    public virtual ICollection<StudentCourse> StudentCourses { get; set; }

    public Course() {
        StudentCourses = new List<StudentCourse>();
    }
}

すべてが私のDbContextクラスにリンクされており、期待どおりに機能しています。コースに参加したすべての学生を見つけたいので、次のようにします。

var query = db.Students
            .Where(s => s.StudentCourses.Course.ID == 11); 

しかし、何らかの理由でEFがStudentCourseとCourseの間のリンクを認識できないため、失敗します。エラーメッセージは次のとおりです。

'System.Collections.Generic.ICollection'には'Course'の定義が含まれておらず、タイプ'System.Collections.Generic.ICollection'の最初の引数を受け入れる拡張メソッド'Course'が見つかりませんでした(usingディレクティブがありませんか?またはアセンブリリファレンス?)。

ただし、以下は正常に機能します。

var query = db.StudentCourses
            .Where(s => s.Course.ID == 11)
            .Select(s=>s.Students);

これはバグですか、それとも私は何か間違ったことをしていますか?

4

2 に答える 2

1

StudentCoursesはコースのリストであり、.Courseを使用して1つのコースにアクセスすることはできません。これを行うには、select、where、anyなどの個々のレコードで機能する句を使用する必要があります(ラムダ式を使用するIEnumerable拡張機能のほとんどは、この目的で使用します)。

var query = db.Students.Where(s => s.StudentCourses.Any(r => r.Course.CourseID == 11)); 

db.Studentsで作業したい場合は問題ありませんが、投稿した2番目の例は、おそらく、実行していることに意味的に近いものです。StudentCoursesは、学生とコースの間のつながりを表しています。where句が特定のコースに制限されている場合、select句は、接続されている学生に学生コースコレクションを投影します。

于 2012-05-11T16:32:01.090 に答える
1

コードにこの部分があるのはなぜですか?

public Student(){
    StudentCourses = new List<StudentCourse>();
}

私がそれをするときにその部分を含める必要はありません、それは持っているだけでうまくいきます

public virtual ICollection<StudentCourse> StudentCourses { get; set; }

すべてそれ自体で。事前にリストを割り当てることで、内部準備が機能しないようにしています。


その点に注意してください

var query = db.Students
              .Where(s => s.StudentCourses.Course.ID == 11);

StunderdCoursesは遅延評価される可能性があるため、必ずしも機能するとは限りません。次を使用することをお勧めします。

var query = db.Students
              .Include("StudentCourses")
              .Where(s => s.StudentCourses.Course.ID == 11);

これにより、各学生のStudentCoursesもクエリに含まれるようになります。


上記のクエリは、すべての学生をフェッチしているため非効率的であり、各学生についてすべてのコースをフェッチしているため、最初に適切なコースを検索してから所属する学生を見つけるため、最後に提案したコードの方がはるかに優れていることに注意してください。それに:

var query = db.StudentCourses
              .Include("Course")
              .Where(s => s.Course.ID == 11)
              .Select(s=>s.Students);

Include遅延評価を行うサーバーで必要なagainの使用に注意してください。


ただし、クラスには実際にはCourseIDプロパティがあるため、次のこともできます。

var query = db.StudentCourses
              .Where(s => s.CourseID == 11)
              .Select(s=>s.Students);
于 2012-05-12T11:00:58.497 に答える