Chèn / Cập nhật nhiều Khung thực thể. Tôi phải làm nó như thế nào?


104

Tôi đang sử dụng EF4 và mới sử dụng nó. Tôi có rất nhiều thứ trong dự án của mình và dường như không thể tìm ra cách chèn hoặc cập nhật. Tôi đã xây dựng một dự án nhỏ chỉ để xem nó nên được mã hóa như thế nào.

Giả sử tôi có 3 bàn

  1. Lớp: ClassID-ClassName
  2. Sinh viên: StudentID-FirstName-Họ
  3. Lớp học sinh: StudentID-ClassID

Sau khi thêm tất cả mối quan hệ và cập nhật mô hình thông qua trình duyệt mô hình, tôi nhận thấy rằng StudentClass không xuất hiện, đây dường như là hành vi mặc định.

Bây giờ tôi cần thực hiện cả Chèn và Cập nhật. Bạn làm nó như thế nào? Bất kỳ mẫu mã hoặc liên kết nào mà tôi có thể tải xuống một ví dụ, hoặc bạn có thể dành 5 phút không?

Câu trả lời:


139

Về thực thể (hoặc đối tượng), bạn có một Classđối tượng có một tập hợp Studentsvà một Studentđối tượng có một tập hợp Classes. Vì StudentClassbảng của bạn chỉ chứa Id và không có thông tin bổ sung, EF không tạo thực thể cho bảng tham gia. Đó là hành vi đúng và đó là những gì bạn mong đợi.

Bây giờ, khi thực hiện chèn hoặc cập nhật, hãy cố gắng suy nghĩ về các đối tượng. Ví dụ: nếu bạn muốn chèn một lớp có hai sinh viên, hãy tạo Classđối tượng, các Studentđối tượng, thêm sinh viên vào Studentstập hợp lớp, hãy thêm Classđối tượng vào ngữ cảnh và gọi SaveChanges:

using (var context = new YourContext())
{
    var mathClass = new Class { Name = "Math" };
    mathClass.Students.Add(new Student { Name = "Alice" });
    mathClass.Students.Add(new Student { Name = "Bob" });

    context.AddToClasses(mathClass);
    context.SaveChanges();
}

Thao tác này sẽ tạo một mục nhập trong Classbảng, hai mục nhập trong Studentbảng và hai mục nhập trong StudentClassbảng liên kết chúng với nhau.

Về cơ bản bạn cũng làm như vậy đối với các bản cập nhật. Chỉ cần tìm nạp dữ liệu, sửa đổi đồ thị bằng cách thêm và xóa các đối tượng khỏi bộ sưu tập, gọi SaveChanges. Kiểm tra câu hỏi tương tự này để biết chi tiết.

Chỉnh sửa :

Theo nhận xét của bạn, bạn cần phải chèn một cái mới Classvà thêm hai cái hiện có Studentsvào nó:

using (var context = new YourContext())
{
    var mathClass= new Class { Name = "Math" };
    Student student1 = context.Students.FirstOrDefault(s => s.Name == "Alice");
    Student student2 = context.Students.FirstOrDefault(s => s.Name == "Bob");
    mathClass.Students.Add(student1);
    mathClass.Students.Add(student2);

    context.AddToClasses(mathClass);
    context.SaveChanges();
}

Vì cả hai sinh viên đều đã có trong cơ sở dữ liệu nên chúng sẽ không được chèn vào, nhưng vì chúng hiện đang ở trong Studentsbộ sưu tập của Classhai mục nhập sẽ được chèn vào StudentClassbảng.


Hi, Cảm ơn bạn reply.My Kịch bản của bạn là tôi cần phải chèn 1 entry vào lớp và khi x ví dụ của bạn 2 mục vào StudentClass và không có mục nhập vào Student.I đang bối rối như thế nào tôi làm điều đó
user9969

ĐÓ ĐÃ LÀM VIỆC XỬ LÝ. Theo dõi cập nhật. Có bất cứ điều gì đặc biệt mà tôi cần làm không? EG. Ví dụ: chỉ cần cập nhật tên className.
user9969

3
Điều này sẽ thêm chi phí tìm nạp từ cơ sở dữ liệu các mục mà người ta cần thêm. Phương thức Attach chỉ có thể được sử dụng để thêm một quan hệ. Xem msdn.microsoft.com/en-us/data/jj592676.aspx và cả stackoverflow.com/questions/11355019/…
Gnomo

3
AddToClasses là DbSet cho Class?
Jo Smo

1
Đừng quên khởi tạo bộ sưu tập của bạn trong hàm tạo cho Lớp và Sinh viên. Ví dụ: public Class () {this.Students = new HashSet <Student> (); }
user1040323

40

Hãy thử cái này để cập nhật:

[HttpPost]
public ActionResult Edit(Models.MathClass mathClassModel)
{
    //get current entry from db (db is context)
    var item = db.Entry<Models.MathClass>(mathClassModel);

    //change item state to modified
    item.State = System.Data.Entity.EntityState.Modified;

    //load existing items for ManyToMany collection
    item.Collection(i => i.Students).Load();

    //clear Student items          
    mathClassModel.Students.Clear();

    //add Toner items
    foreach (var studentId in mathClassModel.SelectedStudents)
    {
        var student = db.Student.Find(int.Parse(studentId));
        mathClassModel.Students.Add(student);
    }                

    if (ModelState.IsValid)
    {
       db.SaveChanges();
       return RedirectToAction("Index");
    }

    return View(mathClassModel);
}

điều này đã lưu ngày của tôi cảm ơn bạn !!! phần quan trọng của chúng là item.Collection (i => i.Students) .Load (); phần
Gerrie Pretorius

Chỉ là một lưu ý nhỏ, tôi đã gặp phải lỗi InvalidOperationException khi làm điều đó, một cái gì đó giống như thực thể của tôi không tồn tại trong ngữ cảnh. Tôi vừa gọi context.MyEntityCollection.Attach (myEntity) để giải quyết nó.
Kilazur

Sẽ không bao giờ tìm ra điều đó. Cảm ơn rất nhiều.
Bãi biển Jared

1
Cho phép tôi thêm lời cảm ơn ở đây. Tôi đã viết và kiểm tra hơn 130 dòng mã trong 4 ngày qua để cố gắng hoàn thành nhiệm vụ này nhưng không thể thực hiện được. Đã thử điều này và mọi thứ hoạt động hoàn hảo. Mặc dù tôi không hiểu mục đích của việc thiết lập biến item và sau đó không sử dụng nó nữa, nhưng tôi rất vui vì nó hoạt động! Cảm ơn một triệu bajillion !!!! :)
Dude-Dastic

Xem xét câu hỏi là Chèn VÀ Cập nhật, câu trả lời này hoàn thành câu hỏi và câu trả lời được chấp nhận. Cảm ơn rât nhiều!
Vahx

5

Tôi muốn thêm kinh nghiệm của mình về điều đó. Thật vậy EF, khi bạn thêm một đối tượng vào ngữ cảnh, nó sẽ thay đổi trạng thái của tất cả các đối tượng con và thực thể liên quan thành Đã thêm. Mặc dù có một ngoại lệ nhỏ trong quy tắc ở đây: nếu các thực thể con / thực thể liên quan đang được theo dõi bởi cùng một ngữ cảnh, EF hiểu rằng những thực thể này tồn tại và không thêm chúng vào. Vấn đề xảy ra khi ví dụ, bạn tải các thực thể con / thực thể có liên quan từ một số ngữ cảnh khác hoặc một ui web, v.v. và sau đó có, EF không biết gì về các thực thể này và đi và thêm tất cả chúng. Để tránh điều đó, chỉ cần lấy khóa của các thực thể và tìm chúng (ví dụ: context.Students.FirstOrDefault(s => s.Name == "Alice"))trong cùng ngữ cảnh mà bạn muốn thực hiện thêm.


3

Tôi sử dụng cách sau để xử lý mối quan hệ nhiều-nhiều trong đó chỉ có các khóa ngoại mới tham gia.

Vì vậy, để chèn :

public void InsertStudentClass (long studentId, long classId)
{
    using (var context = new DatabaseContext())
    {
        Student student = new Student { StudentID = studentId };
        context.Students.Add(student);
        context.Students.Attach(student);

        Class class = new Class { ClassID = classId };
        context.Classes.Add(class);
        context.Classes.Attach(class);

        student.Classes = new List<Class>();
        student.Classes.Add(class);

        context.SaveChanges();
    }
}

Để xóa ,

public void DeleteStudentClass(long studentId, long classId)
{
    Student student = context.Students.Include(x => x.Classes).Single(x => x.StudentID == studentId);

    using (var context = new DatabaseContext())
    {
        context.Students.Attach(student);
        Class classToDelete = student.Classes.Find(x => x.ClassID == classId);
        if (classToDelete != null)
        {
            student.Classes.Remove(classToDelete);
            context.SaveChanges();
        }
    }
}

1

Trong khung thực thể, khi đối tượng được thêm vào ngữ cảnh, trạng thái của nó sẽ thay đổi thành Đã thêm. EF cũng thay đổi trạng thái của từng đối tượng để được thêm vào cây đối tượng và do đó bạn gặp phải lỗi vi phạm khóa chính hoặc các bản ghi trùng lặp được thêm vào bảng.


2
Vui lòng chỉnh sửa để cung cấp đủ chi tiết để người dùng không phải truy cập blog của bạn để nhận câu trả lời.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.