다 대다 Entity Framework 삽입 / 업데이트. 어떻게하나요?


104

EF4를 사용하고 있으며 처음 사용하고 있습니다. 내 프로젝트에 다대 다가 있고 삽입 또는 업데이트 방법을 해결할 수없는 것 같습니다. 코딩 방법을보기 위해 작은 프로젝트를 빌드했습니다.

테이블이 3 개 있다고 가정 해 보겠습니다.

  1. 클래스 : ClassID-ClassName
  2. 학생 : StudentID-FirstName-Surname
  3. StudentClass : StudentID-ClassID

모든 관계를 추가하고 모델 브라우저를 통해 모델을 업데이트 한 후 StudentClass가 나타나지 않는 것으로 나타났습니다. 이것이 기본 동작 인 것 같습니다.

이제 삽입과 업데이트를 모두 수행해야합니다. 어떻게하나요? 예제를 다운로드 할 수있는 코드 샘플이나 링크가 있습니까? 아니면 5 분 정도 여유가 있습니까?

답변:


139

엔터티 (또는 개체)의 관점 Class에서 컬렉션이 Students있는 Student개체 와 컬렉션이 있는 개체가 있습니다 Classes. 당신 때문에 StudentClass테이블에만 ID와 별도의 정보를 포함, EF는 가입 테이블에 대한 엔티티를 생성하지 않습니다. 그것은 올바른 행동이며 당신이 기대하는 것입니다.

이제 삽입이나 업데이트를 할 때 객체의 관점에서 생각하십시오. 예를 들어 두 명의 학생이있는 클래스를 삽입하려면 Class객체, Student객체를 만들고 학생을 클래스 Students컬렉션에 추가 Class하고 컨텍스트에 객체를 추가 하고 다음을 호출합니다 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();
}

이것은에 항목이 만들어집니다 Class테이블의 두 엔트리 Student테이블과 두 개의 항목 StudentClass들을 함께 연결 테이블을.

기본적으로 업데이트에 대해 동일하게 수행합니다. 데이터를 가져오고 컬렉션에서 개체를 추가 및 제거하여 그래프를 수정하고 SaveChanges. 자세한 내용은 이 유사한 질문 을 확인 하십시오.

편집 :

귀하의 의견에 따라 새 항목을 삽입하고 Class두 개의 기존 항목 Students을 추가 해야합니다.

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();
}

두 학생이 이미 데이터베이스에 있으므로 삽입되지 않지만 이제 Students.NET 컬렉션에 있으므로 Class두 항목이 StudentClass테이블에 삽입됩니다 .


안녕하세요, 답장을 보내 주셔서 감사합니다. 내 시나리오는 수업에 1 개의 항목을 삽입하고 x의 예로서 StudentClass에 2 개의 항목을 입력하고 Student에는 항목을 입력하지 않아야한다는 것입니다. 어떻게하는지 혼란 스럽습니다
user9969

그게 TREAT. 업데이트에 관해서는 내가해야 할 특별한 일이 있습니까? 예 : 예를 들어 className을 업데이트하십시오.
user9969 2010

3
이것은 데이터베이스에서 추가해야하는 항목을 가져 오는 오버 헤드를 추가합니다. Attach 메서드는 관계 만 추가하는 데 사용할 수 있습니다. msdn.microsoft.com/en-us/data/jj592676.aspxstackoverflow.com/questions/11355019/…
Gnomo 2014 년

3
AddToClasses는 클래스 용 DbSet입니까?
Jo Smo

1
Class 및 Student 생성자에서 컬렉션을 초기화하는 것을 잊지 마십시오. 예 : public Class () {this.Students = new HashSet <Student> (); }
user1040323

40

업데이트를 위해 이것을 시도하십시오.

[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);
}

이것은 내 하루를 구했습니다. 감사합니다! 핵심 부분은 item.Collection (i => i.Students) .Load (); 부분
게리 Pretorius

참고로, 그렇게 할 때 InvalidOperationException이 발생했습니다. 내 엔터티와 같은 것이 컨텍스트에 존재하지 않았습니다. 방금 context.MyEntityCollection.Attach (myEntity)를 호출하여 처리했습니다.
Kilazur 2015

그것을 결코 이해하지 못했을 것입니다. 정말 감사합니다.
Jared Beach

1
여기에 감사를 추가하겠습니다. 지난 4 일 동안 130 줄 이상의 코드를 작성하고 테스트했지만이 작업을 수행하려고했지만 할 수 없었습니다. 이것을 시도했고 모든 것이 완벽하게 작동했습니다. 항목 변수 를 설정하는 목적을 이해하지 못하고 전혀 사용하지 않지만 작동하는 것이 기쁩니다! 백만 바질 리온 감사합니다 !!!! :)
Dude-Dastic

질문이 삽입 및 업데이트임을 고려하면이 답변은 질문과 허용 된 답변을 완성합니다. 대단히 감사합니다!
Vahx

5

나는 그것에 내 경험을 추가하고 싶었습니다. 실제로 EF는 컨텍스트에 개체를 추가하면 모든 자식 및 관련 엔터티의 상태가 추가됨으로 변경됩니다. 여기 규칙에는 작은 예외가 있지만 자식 / 관련 엔터티가 동일한 컨텍스트에서 추적되는 경우 EF는 이러한 엔터티가 존재한다는 것을 이해하고 추가하지 않습니다. 예를 들어 다른 컨텍스트 또는 웹 UI 등에서 자식 / 관련 엔터티를로드 한 다음 예, EF는 이러한 엔터티에 대해 아무것도 모르고 모두 추가 할 때 문제가 발생합니다. 이를 방지하려면 엔티티의 키를 가져 와서 찾으십시오 (예 : context.Students.FirstOrDefault(s => s.Name == "Alice"))추가를 수행하려는 동일한 컨텍스트에서).


3

외래 키만 관련된 다 대다 관계를 처리하기 위해 다음 방법을 사용합니다.

따라서 삽입 :

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();
    }
}

대한 삭제 ,

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

개체 프레임 워크에서 개체가 컨텍스트에 추가되면 해당 상태가 추가됨으로 변경됩니다. EF는 또한 개체 트리에 추가 할 각 개체의 상태를 변경하므로 기본 키 위반 오류가 발생하거나 테이블에 중복 레코드가 추가됩니다.


2
제발 편집은 사용자가 답변을 얻을 귀하의 블로그를 방문하지 않도록 충분한 세부 사항을 제공합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.