Arbeiten mit Fremdschlüsseln (Entity Framework)
Ab .NET Framework Version 4 können Sie Fremdschlüsseleigenschaften für Entitätstypen verfügbar machen und Beziehungen durch Fremdschlüssel definieren. Die Option Fremdschlüsselspalten in das Modell einbeziehen des Entity Data Model -Assistenten ist standardmäßig aktiviert. Wenn diese Option aktiviert wird, verfügen die generierten Entitätsobjekte über skalare Eigenschaften, die Fremdschlüsselspalten zugeordnet sind.
Fremdschlüsseleigenschaften ermöglichen Ihnen, eine Beziehung zu erstellen oder zu ändern, ohne das Prinzipalobjekt abzufragen. Wenn Sie Fremdschlüsseleigenschaften einbeziehen, können Sie eine Beziehung immer noch ändern, indem Sie den Verweis des abhängigen Elements auf das Prinzipalobjekt aktualisieren oder einer Auflistung des Prinzipalobjekts ein abhängiges Objekt hinzufügen. Auf Verweise und Auflistungen von Entitäten wird üblicherweise über die Navigationseigenschaften zugegriffen. Weitere Informationen finden Sie unter Navigationseigenschaften.
Entity Framework versucht, Verweise, Auflistungen und Fremdschlüsseleigenschaften synchron zu halten. Wenn Sie eine Fremdschlüsseleigenschaft eines abhängigen Objekts aktualisieren, sollten der Verweis auf dieses Objekt und die Auflistung des Prinzipalobjekts synchronisiert werden. Damit diese Synchronisierung stattfinden kann, müssen die Entitäten an den Objektkontext angefügt werden, und die Entitäten müssen vom Entity Framework verfolgt werden. Weitere Informationen finden Sie unter Identitätsauflösung, Zustandsverwaltung und Änderungsnachverfolgung (Entity Framework) und Definieren und Verwalten von Beziehungen (Entity Framework).
Die Beispiele in diesem Thema beruhen auf dem Modell "School". Die Entitätstypen in diesen Beispielen werden von den Entity Data Model -Tools generiert. Die generierten Typen werden vom Entity Framework verfolgt. Wenn Sie mit POCO-Typen arbeiten, finden Sie weitere Informationen unter Verfolgen von Änderungen in POCO-Entitäten (Entity Framework).
Im folgenden Beispiel wird gezeigt, wie die Beziehung zwischen zwei vorhandenen Objekten geändert wird.
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();
}
Im folgenden Beispiel wird gezeigt, wie mittels der Festlegung von Fremdschlüsseleigenschaften die Beziehung zwischen dem neuen abhängigen Objekt und vorhandenen Prinzipalobjekten festgelegt wird.
' 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();
}
Im folgenden Beispiel wird gezeigt, wie die Beziehung zwischen dem neuen abhängigen Element und dem neuen Prinzipalobjekt festgelegt wird.
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();
}
Mit Fremdschlüssel-Zuordnung können Sie die Beziehung mithilfe des Verweises immer noch so festlegen, wie Sie es in der Version vor der Version 4 des Entity Framework gemacht haben.
' 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();
}
Das folgende Beispiel zeigt eine einfache Kommunikation zwischen einem Client und einem Dienst, wobei der Client von dem Dienst ein Objekt anfordert, der Client das Objekt aktualisiert und den Dienst auffordert, die Änderungen in der Datenbank zu speichern.
Der Dienst definiert zwei Methoden:
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();
}
}
Der Client aktualisiert die Werte der Fremdschlüsseleigenschaften und sendet das aktualisierte Objekt an den Dienst:
' 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);
Siehe auch
Konzepte
Definieren und Verwalten von Beziehungen (Entity Framework)
Arbeiten mit POCO-Entitäten (Entity Framework)