2017-07-04 8 views
0

は、この例ではコードを取る: http://www.entityframeworktutorial.net/code-first/configure-many-to-many-relationship-in-code-first.aspx最も効率的な方法(複数のマッピングを作成する)

を複数を追加するための最も効率的な方法だろう何私がコースIDを持っていると、学生にコースを教えてもらえますか?

private static void AddCoursesToStudent(SchoolDBContext context, Student student, List<int> CourseIds) 
    {} 

をそして、私の現在の試行は、次のようになります:

ので、例えば、関数は次のようになり

特にで混合、動作しますが、少しずさん思わ
public static async Task AddCoursesToStudentAsync(SchoolDBContext context, Student student, List<int> CourseIds) 
    { 
     await context.Courses.Where(x => CourseIds.Contains(x.CourseId)).ForEachAsync(x => x.Students.Add(student)); 
     context.SaveChanges(); 
    } 

    private static void AddCoursesToStudent(SchoolDBContext context, Student student, List<int> CourseIds) 
    { 
     var task = AddCoursesToStudentAsync(context,student,CourseIds); 
     task.Wait(); 
    } 

非同期私はまた、 "ForEach"と組み合わせた "Where"がどこかのすべてのレコードをプルアップすると考えています。それは最初に、我々は通常、手動でこの場合には次のようになり、「マッピングテーブル」を作成していたコードではなかった他のプロジェクトで

public class StudentCourse 
{ 
    [Key] [Column(Order = 0)] 
    private int StudentId; 
    [Key] 
    [Column(Order = 1)] 
    private int CourseId; 

    public StudentCourse(int courseIde, int studentId) 
    { 
     StudentId = studentId; 
     CourseId = courseIde; 
    } 
} 

そして、あなたが行くと何かのように:

public static void AddCoursesToStudentMaps(SchoolDBContext context, Student student, List<int> CourseIds) 
    { 
     List<StudentCourse> maps = CourseIds.ConvertAll(courseId => new StudentCourse(courseId, student.StudentId)).ToList(); 
     context.StudentCourses.AddRange(maps); 
    } 

エンティティフレームワークがこれを管理する方法でこれを行うとよいでしょう。おそらく、私は単に学生コースのクラスを作成し、それをコンテキストに追加できますか?しかし、それはその点を打ち破っているようです。特に、多くのものがたくさんあり、EFがマッピングテーブルを作成してコードを削減する必要があるためです。私は、EFがマッピングを自動的に作成できるかどうか、それが行った作業をやり直すことなく新しいリンクを効率的に作成する方法が必要だと思いますか?

誰bashを持っているしたい場合、これはあなたを取得し、実行する必要がありますので、私は、怠惰なセットアップ機能と、この例のコードを作成してこれをテストするために:

static void Main(string[] args) 
    { 
     Run(); 
    } 

    private static void Run() 
    { 
     using (SchoolDBContext context = new SchoolDBContext()) 
     { 
      /* Run once 
      * SetUp(context); 
      */ 
      Test(context); 
      Output(context); 
     } 
    } 

    static void SetUp(SchoolDBContext context) 
    { 
     context.Students.Add(new Student() { StudentName = "Gerry" }); 
     context.Students.Add(new Student() { StudentName = "Bob" } ); 
     context.Students.Add(new Student() { StudentName = "Jane" }); 

     context.Courses.Add(new Course() { CourseName = "Science" }); 
     context.Courses.Add(new Course() { CourseName = "Math" } ); 
     context.Courses.Add(new Course() { CourseName = "History" }); 
     context.Courses.Add(new Course() { CourseName = "Other History" }); 
     context.Courses.Add(new Course() { CourseName = "Roman History" }); 
     context.Courses.Add(new Course() { CourseName = "English History" }); 
     context.Courses.Add(new Course() { CourseName = "Super History" }); 
     context.Courses.Add(new Course() { CourseName = "Tudor History" }); 
     context.Courses.Add(new Course() { CourseName = "Queen History" }); 
     context.Courses.Add(new Course() { CourseName = "King History" }); 
     context.SaveChanges(); 
    } 

    public static void Test(SchoolDBContext context) 
    { 

     var ids = context.Courses.Where(x => x.CourseName.Contains("History")).Select(x => x.CourseId).ToList(); 
     var student = context.Students.FirstOrDefault(x => x.StudentName == "Bob"); 
     AddCoursesToStudent(context, student, ids); 
    } 

    private static void Output(SchoolDBContext context) 
    { 
     OutputStudents(context); 
    } 

    private static void OutputStudents(SchoolDBContext context) 
    { 
     var allStudents = context.Students.ToList(); 
     foreach (var student in allStudents) 
     { 
      Console.WriteLine($"Student: {student.StudentName}"); 
      if (student.Courses.Any()) 
      { 
       Console.WriteLine("is enrolled on"); 
       Console.WriteLine("**************************"); 
       foreach (var contextCourseStudent in student.Courses) 
       { 
        Console.WriteLine("  " + contextCourseStudent.CourseName); 
       } 
       Console.WriteLine("************************ "); 
      } 
      Console.WriteLine("-------------------------"); 
     } 
     Console.WriteLine("Press enter to close..."); 
     Console.ReadLine(); 
    } 
    private static void OutputCourse(SchoolDBContext context) 

P.S.を単にコースのリストを持たない理由は、IDリストを送信するフォーム/アプリケーションなどが既に設定されているということです。前述のように、それらのモデルをデータベースから取り出して純粋に追加するのは愚かで非効率的です親に

+0

を。また、各コースの受講生のリストが必要な場合は、そのコースを受講するために実際にデータベースに行くことなく、どのように取得する予定ですか?そのため、多対多の関係は常に第3のエンティティでモデル化されます。 –

+0

謝罪、私はちょうど仕事を見せたいと思っていましたが、あなたが私の質問を誤解したように誤解を招くように、私はコースIDは持っています。第3のエンティティを作成することはできますが、EFは役に立つリンクテーブルを「フードの下に」作成することができますが、EFを無視して自分の第3のエンティティを作成しない限り、非効率的です。 – chrispepper1989

答えて

3

私は暗黙のリンクテーブルを持つmany-to-manyはコードファースト固有ではないと思います。また、クエリをより簡単で自然にする一方で、既に見てきたように、リンクを変更すると明白な欠点があります。

それは効率的スタブエンティティを使用して追加する新しいリンクを実装することが可能です:

static void AddCoursesToStudent(SchoolDBContext context, Student student, List<int> CourseIds) 
{ 
    student.Courses = CourseIds.Select(id => context.Courses.Attach(new Course { CourseId = id })).ToList(); 
    context.SaveChanges(); 
} 

これは動作しますが、以下の制約の下で:

(1)contextがために特別に作成されていますこのコール
(2)studentは既に添付されていますcontext
(3)CourseIdsはすべてd atabase
(4)の一部に関連してロードされたいかなるCourseエンティティがありませんCourseIds
(5)初期student.Coursesコレクションが熱心または遅延ロードではありません。これは(追加と削除項目を決定することによって、すべてのリンクにを交換VS)追加リンクに操作を強制するために、具体的である
(6)あなたはその後contextまたはCourseオブジェクトのいずれかを使用しない以外のすべてのそれらのプロパティので、 PKは現実的ではありません。

すべての制約を考慮例:あなたの質問は、このような簡単な質問にはあまりにも多くのテキストを持っている

public void AddCoursesToStudent(int studentId, List<int> coursesIds) 
{ 
    using (var context = new SchoolDBContext()) 
    { 
     var student = context.Students.Find(studentId); 
     AddCoursesToStudent(context, student, coursesIds); 
    } 
} 
+0

1対多の関係のためにこれはありませんか?私はEFがこれを内部的にどのようにしているのかよく分かりませんが、多くを片側に追加する(つまり、コースを学生に割り当てる)ことは、他の人に多くを追加する(つまり、新しい学生を各コースに割り当てる)のはどうですか? –

+0

1 - コンテキストが使用ブロック内にあるなど、Webプロジェクトではどのように動作しますか? – chrispepper1989

+0

2 - これはあなたが既にDB内に存在するか、この文脈で変更されている/具体的に* this * contextから抜粋したことを意味しますか? – chrispepper1989

関連する問題