외래 키 사용(Entity Framework)

.NET Framework 버전 4부터 엔터티 형식에 외래 키 속성을 노출하고 외래 키를 통해 관계를 정의할 수 있습니다. 엔터티 데이터 모델 마법사의 모델에 외래 키 열 포함 옵션은 기본적으로 선택되어 있습니다. 이 옵션이 선택되어 있으면 생성된 엔터티 개체에 외래 키 열에 매핑하는 스칼라 속성이 포함됩니다.

외래 키 속성을 사용하면 주 개체를 쿼리하지 않고도 관계를 만들거나 수정할 수 있습니다. 외래 키 속성을 포함할 때 종속 개체에서 주 개체에 대한 참조를 업데이트하거나 주 개체에서 컬렉션에 종속 개체를 추가하여 관계를 수정할 수도 있습니다. 엔터티의 참조 및 컬렉션에 액세스하려면 일반적으로 탐색 속성을 사용합니다. 자세한 내용은 탐색 속성을 참조하십시오.

Entity Framework 에서는 참조, 컬렉션 및 외래 키 속성의 동기화 상태를 유지하려고 합니다. 종속 개체의 외래 키 속성을 업데이트할 경우 이 개체의 참조와 주 개체의 컬렉션이 동기화되어야 합니다. 이 동기화가 수행되려면 엔터티가 개체 컨텍스트에 연결되어 있고 Entity Framework 에서 엔터티를 추적해야 합니다. 자세한 내용은 ID 확인, 상태 관리 및 변경 내용 추적(Entity Framework)관계 정의 및 관리(Entity Framework)를 참조하십시오.

이 항목의 예제는 School 모델을 기반으로 합니다. 예제의 엔터티 형식은 엔터티 데이터 모델 도구에 의해 생성됩니다. 생성된 형식은 Entity Framework에 의해 추적됩니다. POCO 형식을 사용하는 경우에는 POCO 엔터티에서 변경 내용 추적(Entity Framework)을 참조하십시오.

다음 예제에서는 두 기존 개체 간의 관계를 변경하는 방법을 보여 줍니다.

Dim studentId As Integer = 6
Dim enrollmentID As Integer = 2

Using context = New SchoolEntities()
    ' Get StudentGrade. 
    Dim grade = (From g In context.StudentGrades
                 Where g.EnrollmentID = enrollmentID
                 Select g).First()

    ' Change the relationship. 
    grade.StudentID = studentId
    ' You can access Person reference object on the grade object 
    ' without loading the reference explicitly when 
    ' the lazy loading option is set to true. 
    Console.WriteLine(grade.Person.PersonID)
    ' Save the changes. 
    context.SaveChanges()
End Using
int studentId = 6;
int enrollmentID = 2;

using (var context = new SchoolEntities())
{
    // Get StudentGrade.
    var grade = (from g in context.StudentGrades
                 where g.EnrollmentID == enrollmentID
                 select g).First();

    // Change the relationship.
    grade.StudentID = studentId;
    // You can access Person reference object on the grade object
    // without loading the reference explicitly when
    // the lazy loading option is set to true.
    Console.WriteLine(grade.Person.PersonID);
    // Save the changes.
    context.SaveChanges();
}

다음 예제에서는 외래 키 속성을 설정하여 새 종속 개체와 기존 주 개체 간의 관계를 설정하는 방법을 보여 줍니다.

' The following example creates a new StudentGrade object and associates 
' the StudentGrade with the Course and Person by 
' setting the foreign key properties. 

Using context As New SchoolEntities()
    ' The database will generate the EnrollmentID. 
    ' To create the association between the Course and StudentGrade, 
    ' and the Student and the StudentGrade, set the foreign key property 
    ' to the ID of the principal. 
    Dim newStudentGrade = New StudentGrade With
    {
        .EnrollmentID = 0,
        .Grade = CDec(4.0),
        .CourseID = 4022,
        .StudentID = 17
    }

    ' Adding the new object to the context will synchronize 
    ' the references with the foreign keys on the newStudentGrade object. 
    context.StudentGrades.AddObject(newStudentGrade)

    ' You can access Course and Student objects on the newStudentGrade object
    ' without loading the references explicitly because
    ' the lazy loading option is set to true in the constructor of SchoolEntities.
    Console.WriteLine("Student ID {0}:", newStudentGrade.Person.PersonID)
    Console.WriteLine("Course ID {0}:", newStudentGrade.Course.CourseID)

    context.SaveChanges()
End Using
// The following example creates a new StudentGrade object and associates
// the StudentGrade with the Course and Person by
// setting the foreign key properties. 

using (SchoolEntities context = new SchoolEntities())
{
    StudentGrade newStudentGrade = new StudentGrade
    {
        // The database will generate the EnrollmentID.
        EnrollmentID = 0,
        Grade = 4.0M,
        // To create the association between the Course and StudentGrade, 
        // and the Student and the StudentGrade, set the foreign key property 
        // to the ID of the principal.
        CourseID = 4022,
        StudentID = 17,
    };

    // Adding the new object to the context will synchronize
    // the references with the foreign keys on the newStudentGrade object.
    context.StudentGrades.AddObject(newStudentGrade);

    // You can access Course and Student objects on the newStudentGrade object
    // without loading the references explicitly because
    // the lazy loading option is set to true in the constructor of SchoolEntities.
    Console.WriteLine("Student ID {0}:", newStudentGrade.Person.PersonID);
    Console.WriteLine("Course ID {0}:", newStudentGrade.Course.CourseID);
    
    context.SaveChanges();
}

다음 예제에서는 새 종속 개체와 새 주 개체 간의 관계를 설정하는 방법을 보여 줍니다.

Using context = New SchoolEntities()
    ' The database will generate PersonID. 
    ' The object context will get the ID 
    ' After the SaveChanges is called. 
    Dim newStudent = New Person With
    {
        .PersonID = 0,
        .LastName = "Li",
        .FirstName = "Yan"
     }
    ' The database will generate EnrollmentID. 
    ' The object context will get the ID 
    ' After the SaveChanges is called. 
    Dim newStudentGrade = New StudentGrade With
    {
        .EnrollmentID = 0,
        .Grade = CDec(4.0),
        .StudentID = 50
    }

    ' Add newStudent to object context. 
    ' The newStudent's state will change from Detached to Added. 
    context.People.AddObject(newStudent)

    ' To associate the new objects you can do one of the following: 
    ' Add the new dependent object to the principal object: newStudent.StudentGrades.Add(newStudentGrade). 
    ' Assign the reference (principal) object to the navigation property of the 
    ' dependent object: newStudentGrade.Person = newStudent. 
    ' Both of these methods will synchronize the navigation properties on both ends of the relationship. 

    ' Adding the newStudentGrade to newStudent will change newStudentGrade's status 
    ' from Detached to Added. 
    newStudent.StudentGrades.Add(newStudentGrade)
    ' Navigation properties in both directions will work immediately. 
    Console.WriteLine("Access StudentGrades navigation property to get the count: ", _
                      newStudent.StudentGrades.Count)
    Console.WriteLine("Access Person navigation property: {0} ", _
                      newStudentGrade.Person.FirstName)

    context.SaveChanges()
End Using
using (var context = new SchoolEntities())
{
    Person newStudent = new Person
    {
        // The database will generate PersonID.
        // The object context will get the ID 
        // After the SaveChanges is called.
        PersonID = 0,
        LastName = "Li",
        FirstName = "Yan"
    };
    StudentGrade newStudentGrade = new StudentGrade
    {
        // The database will generate EnrollmentID.
        // The object context will get the ID 
        // After the SaveChanges is called.
        EnrollmentID = 0,
        Grade = 4.0M,
        StudentID = 50
    };

    // Add newStudent to object context. 
    // The newStudent's state will change from Detached to Added.
    context.People.AddObject(newStudent);

    // To associate the new objects you can do one of the following:
    // Add the new dependent object to the principal object: newStudent.StudentGrades.Add(newStudentGrade).
    // Assign the reference (principal) object to the navigation property of the 
    // dependent object: newStudentGrade.Person = newStudent.
    // Both of these methods will synchronize the navigation properties on both ends of the relationship.

    // Adding the newStudentGrade to newStudent will change newStudentGrade's status
    // from Detached to Added.
    newStudent.StudentGrades.Add(newStudentGrade);
    // Navigation properties in both directions will work immediately.
    Console.WriteLine("Access StudentGrades navigation property to get the count: ",
        newStudent.StudentGrades.Count);
    Console.WriteLine("Access Person navigation property: {0} ", newStudentGrade.Person.FirstName);

    context.SaveChanges();
}

외래 키 연결이 있는 경우 Entity Framework 4 이전 버전에서처럼 참조를 사용하여 관계를 설정할 수도 있습니다.

' The following example creates a new StudentGrade and associates 
' the StudentGrade with the Course and Person by 
' setting the navigation properties to the Course and Person objects that were returned 
' by the query. 
' You do not need to call AddObject() in order to add the grade object 
' to the context, because when you assign the reference 
' to the navigation property the objects on both ends get synchronized by the Entity Framework. 
' Note, that the Entity Framework will not synchronize the ends untill the SaveChanges method 
' is called if your objects do not meet the change tracking requirements. 
Using context = New SchoolEntities()
    Dim courseID = 4022
    Dim course = (From c In context.Courses
                 Where c.CourseID = courseID
                 Select c).First()

    Dim personID = 17
    Dim student = (From p In context.People
                  Where p.PersonID = personID
                  Select p).First()

    ' The database will generate the EnrollmentID. 
    ' Use the navigation properties to create the association between the objects. 
    Dim newStudentGrade = New StudentGrade With
    {
        .EnrollmentID = 0,
        .Grade = CDec(4.0),
        .Course = course,
        .Person = student
    }
    context.SaveChanges()
End Using
// The following example creates a new StudentGrade and associates
// the StudentGrade with the Course and Person by
// setting the navigation properties to the Course and Person objects that were returned
// by the query. 
// You do not need to call AddObject() in order to add the grade object
// to the context, because when you assign the reference 
// to the navigation property the objects on both ends get synchronized by the Entity Framework.
// Note, that the Entity Framework will not synchronize the ends untill the SaveChanges method
// is called if your objects do not meet the change tracking requirements. 
using (var context = new SchoolEntities())
{
    int courseID = 4022;
    var course = (from c in context.Courses
                 where c.CourseID == courseID
                 select c).First();

    int personID = 17;
    var student = (from p in context.People
                  where p.PersonID == personID
                  select p).First();

    StudentGrade grade = new StudentGrade
    {
        // The database will generate the EnrollmentID.
        Grade = 4.0M,
        // Use the navigation properties to create the association between the objects.
        Course = course,
        Person = student
    };
    context.SaveChanges();
}

아래에서는 클라이언트와 서비스 간의 간단한 통신을 보여 줍니다. 이 경우 클라이언트는 서비스에 개체를 요청하고, 개체를 업데이트하고, 변경 내용을 데이터베이스에 저장하도록 서비스를 호출합니다.

서비스에서 두 개의 메서드를 정의합니다.

Private Shared Function GetOriginalValue(ByVal ID As Integer) As StudentGrade
    Dim originalItem As StudentGrade
    Using context As New SchoolEntities()
        originalItem = context.StudentGrades.Where(Function(g) g.EnrollmentID = ID).FirstOrDefault()

        context.Detach(originalItem)
    End Using
    Return originalItem
End Function

Private Shared Sub SaveUpdates(ByVal updatedItem As StudentGrade)
    Using context As New SchoolEntities()
        ' Query for the StudentGrade object with the specified ID. 
        Dim original = (From o In context.StudentGrades
            Where o.EnrollmentID = updatedItem.EnrollmentID
            Select o).First()

        ' Apply changes. 
        context.StudentGrades.ApplyCurrentValues(updatedItem)

        ' Save changes. 
        context.SaveChanges()
    End Using
End Sub
static private StudentGrade GetOriginalValue(int ID)
{
    StudentGrade originalItem;
    using (SchoolEntities context
        = new SchoolEntities())
    {
        originalItem =
            context.StudentGrades.Where(g => g.EnrollmentID == ID).FirstOrDefault();

        context.Detach(originalItem);
    }
    return originalItem;
}

static private void SaveUpdates(StudentGrade updatedItem)
{
    using (SchoolEntities context
        = new SchoolEntities())
    {
        // Query for the StudentGrade object with the specified ID.
        var original = (from o in context.StudentGrades
                         where o.EnrollmentID == updatedItem.EnrollmentID
                         select o).First();

        // Apply changes.
        context.StudentGrades.ApplyCurrentValues(updatedItem);

        // Save changes.
        context.SaveChanges();
    }
}

클라이언트에서 외래 키 속성의 값을 업데이트하고 업데이트된 개체를 서비스로 보냅니다.

' A client calls a service to get the original object. 
Dim studentGrade As StudentGrade = GetOriginalValue(3)
' Change the relationships. 
studentGrade.CourseID = 5
studentGrade.StudentID = 10
' The client calls a method on a service to save the updates. 
// A client calls a service to get the original object.
StudentGrade studentGrade = GetOriginalValue(3);
// Change the relationships.
studentGrade.CourseID = 5;
studentGrade.StudentID = 10;
// The client calls a method on a service to save the updates. 
SaveUpdates(studentGrade);

참고 항목

개념

관계 정의 및 관리(Entity Framework)
POCO 엔터티 사용(Entity Framework)