2017-07-14 3 views
0

記事はhow to update related data with the Entity Framework in an ASP.NET MVC applicationです。インストラクターとしてあなたのコースを選ぶことができるシンプルな大学を実装しています。あなたはUpdateInstructorCoursesは、文字列の配列であるselectedCoursesに基づいて​​から取得したオブジェクトとinstructorToUpdate.Coursesを埋め見ることができるように関連データを作成/更新するためにdbからオブジェクトを取得する必要がありますか?

private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate) 
{ 
    if (selectedCourses == null) 
    { 
     instructorToUpdate.Courses = new List<Course>(); 
     return; 
    } 

    var selectedCoursesHS = new HashSet<string>(selectedCourses); 
    var instructorCourses = new HashSet<int> 
     (instructorToUpdate.Courses.Select(c => c.CourseID)); 
    foreach (var course in db.Courses) 
    { 
     if (selectedCoursesHS.Contains(course.CourseID.ToString())) 
     { 
     if (!instructorCourses.Contains(course.CourseID)) 
     { 
      instructorToUpdate.Courses.Add(course); 
     } 
     } 
     else 
     { 
     if (instructorCourses.Contains(course.CourseID)) 
     { 
      instructorToUpdate.Courses.Remove(course); 
     } 
     } 
    } 
} 

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Edit(int? id, string[] selectedCourses) 
{ 
    if (id == null) 
    { 
     return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
    } 
    var instructorToUpdate = db.Instructors 
     .Include(i => i.Courses) 
     .Where(i => i.ID == id) 
     .Single(); 

    if (TryUpdateModel(instructorToUpdate, "", 
     new string[] { "LastName", "FirstMidName", "HireDate", "OfficeAssignment" })) 
    { 
     try 
     { 
      UpdateInstructorCourses(selectedCourses, instructorToUpdate); 

      db.SaveChanges(); 

      return RedirectToAction("Index"); 
     } 
     catch (Exception e) 
     { 
      //Log the error 
     } 
    } 
    PopulateAssignedCourseData(instructorToUpdate); 
    return View(instructorToUpdate); 
} 

:ここ

は、そのコースのコントローラのバージョンに簡略化されます。

多対多リレーションシップを作成する唯一の方法はありますか? dbからAddのオブジェクトを取得する必要がありますか?関連オブジェクトのIDと更新関連データだけを渡す方が良いのではないでしょうか?

答えて

0

ので、多対多マッピングのために、EFでそれを行うには、2つの方法があります。

1)すでに使用された2つのICollectionプロパティ():この中

public class Instructor 
{ 
    public Int32 Id { get; set; } 
    public ICollection<Course> Courses { get; set; } 
} 
public class Course 
{ 
    public Int32 Id { get; set; } 
    public ICollection<Instructor> Instructors { get; set; } 
} 

は、あなたが指摘したように、そのマッピングテーブルからリストを取得する方法は、あなたがMEMにコレクションをロードすること、ありません、

CREATE TABLE [dbo].[Instructors]([Id]) 
CREATE TABLE [dbo].[Courses]([Id]) 
CREATE TABLE [dbp].[Instructor_Courses_Mapping]([Id],[InstructorId],[CoursesId]) 

:今の場合は、EFのような、マッピングテーブルを使用/生成されます。ナビゲーションプロパティを使用してOryを呼び出します。だから、:

2)ただし、独自のカスタム・マッピングのエンティティとEFのマッピングテーブル生成を無効にすることができます

public class Instructor 
{ 
    public Int32 Id { get; set; } 
    public ICollection<InstructorCourse> InstructorCourses { get; set; } 
} 
public class Course 
{ 
    public Int32 Id { get; set; } 
    public ICollection<InstructorCourse> InstructorCourses { get; set; } 
} 
public class InstructorCourse 
{ 
    public Int32 Id { get; set; } 

    public Int32 InstructorId { get; set; } 
    public Instructor Instructor { get; set; } 

    public Int32 CourseId { get; set; } 
    public Course Course { get; set; } 
} 

さて、EFは、これらのテーブルを生成します。

CREATE TABLE [dbo].[Instructors]([Id]) 
CREATE TABLE [dbo].[Courses]([Id]) 
CREATE TABLE [dbp].[InstructorCourses]([Id],[InstructorId],[CourseId]) 

これができるようになりますdbContextを使用してInstructorCoursesをクエリします。

var instructorCourses = dbContext.Set<InstructorCourse>().Where(c => c.InstructorId == instructorId).ToList() 

あなたはInstructorCourseオブジェクトのリストで、すべてInstructorIdの値があなたの探している値と一致しています。追加/マッピングを削除したい場合はその後、:

//add item 
dbContext.Set<InstructorCourse>().Add(new InstructorCourse() 
{ 
    InstructorId = instructorId, 
    CourseId = courseId 
}); 
dbContext.SaveChanges(); 
//remove item 
var itemToRemove = dbContext.Set<InstructorCourse>().FirstOrDefault(c => c.InstructorId == instructorId && c.CourseId == courseId); 
dbContext.Set<InstructorCourse>().Remove(itemToRemove); 
dbContext.SaveChanges(); 

私はあなたのデータベースの構造がより明確に表しているが、それは、ネストされたLINQのステートメントがより複雑にない、この方法は、はるかにきれいであることが判明し、ヌル(適切なし外部キーの制限)が潜在的により一般的です。

+0

素晴らしい。 Fluent APIのようなものを使って 'InstructorCourse'を導入する方法はありますか?追加のモデルは必要ありませんか? – Mowji

+0

@Mowjiいいえ、私は別の方法を知りません。他の唯一のオプションは、raw SQLを使用してマッピングテーブルから手動で挿入/削除することです(明らかにネガティブです)。 –

関連する問題