Utilisation de clés étrangères (Entity Framework)
À partir de .NET Framework version 4, vous pouvez exposer des propriétés de clé étrangère sur les types d'entité et définir des relations via des clés étrangères. L'option Inclure les colonnes clés étrangères dans le modèle de l'Assistant Entity Data Model est sélectionnée par défaut. Lorsque cette option est sélectionnée, les objets entité générés possèdent des propriétés scalaires qui se mappent aux colonnes clés étrangères.
Les propriétés de clé étrangère vous permettent de créer ou de modifier une relation sans lancer une requête pour l'objet principal. Lorsque vous incluez des propriétés de clé étrangère, vous pouvez toujours modifier une relation en mettant à jour la référence à l'objet principal sur le dépendant ou en ajoutant un objet dépendant à une collection sur l'objet principal. La manière la plus courante d'accéder aux références et aux collections sur les entités est d'utiliser des propriétés de navigation. Pour plus d'informations, consultez Propriétés de navigation.
Entity Framework tente de garder les références, les collections et les propriétés de clé étrangère bien synchronisées. Si vous mettez à jour une propriété de clé étrangère d'un objet dépendant, la référence sur cet objet et la collection sur l'objet principal doivent être synchronisées. Pour que cette synchronisation se produise, les entités doivent être jointes au contexte de l'objet et les entités doivent être suivies par Entity Framework . Pour plus d'informations, consultez Résolution d'identité, gestion des états et suivi des modifications (Entity Framework) et Définition et gestion des relations (Entity Framework).
Les exemples de cette rubrique sont basés sur le Modèle School. Les types d'entité dans ces exemples sont générés par les outils Entity Data Model . Les types générés sont suivis par Entity Framework. Si vous utilisez les types POCO, consultez Suivi des modifications dans les entités POCO (Entity Framework).
L'exemple suivant indique comment modifier la relation entre deux objets existants.
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();
}
L'exemple suivant indique comment définir la relation entre le nouvel objet dépendant et les objets principaux existants en définissant les propriétés de clé étrangère.
' 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();
}
L'exemple suivant indique comment définir la relation entre le nouvel objet dépendant et le nouvel objet principal.
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();
}
Avec l'association de clés étrangères, vous pouvez toujours utiliser la référence pour définir la relation, comme vous le feriez dans la version qui précède 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();
}
Les éléments suivants montrent une communication simple entre un client et un service, où le client demande un objet au service, met à jour l'objet et appelle le service pour enregistrer les modifications apportées à la base de données.
Le service définit deux méthodes :
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();
}
}
Le client met à jour les valeurs des propriétés de clé étrangère et envoie l'objet mis à jour au service :
' 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);
Voir aussi
Concepts
Définition et gestion des relations (Entity Framework)
Utilisation d'entités POCO (Entity Framework)