Procédure pas à pas : sérialiser des entités de suivi automatique (Entity Framework)
La procédure pas à pas dans cette rubrique montre le scénario dans lequel un service Windows Communication Foundation (WCF) expose une série d'opérations qui retournent des graphiques d'entité. Une application cliente manipule ensuite ce graphique et soumet les modifications à une opération de service qui valide et enregistre les mises à jour dans une base de données à l'aide d'Entity Framework. Pour plus d'informations, consultez Utilisation des entités de suivi automatique.
En général, vous souhaiterez séparer le modèle de projet du projet qui contient les types d'entité de suivi automatique. Votre client n'aura ensuite qu'à inclure le projet de types d'entité.
Un moyen d'accomplir cette isolation est de séparer les types d'entité de suivi automatique du modèle et de déplacer le modèle qui génère les types d'entité dans une bibliothèque de classes distincte. L'emplacement du fichier .edmx devra être inclus dans le modèle d'entité de suivi automatique de façon à accéder aux métadonnées. Si vous déplacez des modèles du projet d'origine vers d'autres projets, vous devez ouvrir les fichiers modèles dans un éditeur et modifier la chaîne inputFile à l'emplacement relatif du fichier .edmx. Pour plus d'informations sur l'utilisation des modèles, consultez ADO.NET Self-Tracking Entity Template.
Une autre façon de séparer les types d'entité du modèle est de laisser les fichiers modèles dans le projet d'origine, mais de désactiver la génération de code pour les modèles. Créez un lien vers les modèles d'un projet différent de sorte que le code soit généré dans cet autre projet plutôt que dans celui d'origine. Lorsque vous ajoutez un élément à un projet sous forme de lien, le contenu réel de l'élément est maintenu à l'emplacement indiqué par le projet d'origine. Cette méthode de séparation des types d'entité du modèle est illustrée dans cette procédure pas à pas.
Cette procédure pas à pas effectue les actions suivantes :
Création du projet de bibliothèque de classes qui contient le modèle basé sur School.
Utilisation du modèle Générateur d'entité de suivi automatique ADO.NET pour générer les types d'entité, l'objet ObjectContext typé et une classe d'extension qui contient des méthodes ApplyChanges surchargées.
Création du projet de bibliothèque de classes qui se lie au modèle de types d'entité de suivi automatique créé dans le premier projet.
Création du service WCF qui expose l'ensemble des opérations qui retournent les graphiques d'entité et applique les modifications apportées au client à la base de données à l'aide d'Entity Framework .
Création des applications clientes (console et Windows Presentation Foundation [WPF]) qui manipulent le graphique et soumettent les modifications via les opérations exposées sur le service WCF.
Remarque : |
---|
Vous pouvez télécharger STESchoolModelExample sur le site Exemples de documentation Entity Framework dans la galerie de codes MSDN. |
Pour créer le projet de bibliothèque de classes qui contient les entités de suivi automatique et les classes de contexte de l'objet
Créez un projet de bibliothèque de classes. Entrez STESchoolModel pour le projet et le nom de solution.
Supprimez le fichier de code source par défaut qui a été ajouté au projet.
Utilisez l'Assistant EDM (Entity Data Model) pour générer un modèle basé sur les tables Department, Course, OnlineCourse et OnsiteCourse de la base de données School. Pour plus d'informations, consultez Modèle School.
Ouvrez le fichier .edmx dans ADO.NET Entity Data Model Designer (Concepteur d'entités).
Suivez les instructions de mappage d'héritage dans la rubrique Walkthrough: Mapping Inheritance - Table-per-Type.
Cliquez avec le bouton droit sur une zone vide de l'aire du Concepteur d'entités, pointez sur Ajouter un élément de génération de code, puis sélectionnez Générateur d'entité de suivi automatique ADO.NET. Remplacez le nom du modèle par défaut par SchoolModel.
Remarque : Lorsque vous ajoutez les fichiers modèles au projet, un avertissement de sécurité peut apparaître vous demandant d'accepter l'opération uniquement si vous faites confiance à la source du modèle.Cliquez sur Accepter. Les dossiers SchoolModel.Context.tt et SchoolModel.tt sont ajoutés au projet. Sous le dossier SchoolModel.Context.tt se trouvent deux fichiers qui définissent un objet ObjectContext typé et la classe d'extension qui contient des méthodes ApplyChanges surchargées. Sous le dossier SchoolModel.tt figurent des fichiers qui définissent des types d'entité, ainsi qu'une classe d'assistance qui contient la logique de suivi des modifications utilisée par les entités de suivi automatique.
Les deux étapes suivantes illustrent la désactivation de la génération de code dans ce projet. La génération de code sera activée ultérieurement pour les types de la bibliothèque de classes STESchoolModelTypes et pour le contexte de l'objet du service STESchoolModelService.
Sélectionnez SchoolModel.tt. Dans la fenêtre Propriétés, supprimez TextTemplatingFileGenerator de la propriété CustomTool. Supprimez les fichiers situés sous le dossier SchoolModel.tt.
Sélectionnez SchoolModel.Context.tt. Dans la fenêtre Propriétés, effacez la valeur de la propriété CustomTool. Supprimez les fichiers situés sous le dossier SchoolModel.Context.tt.
Si vous travaillez avec le projet Visual Basic, vous devrez peut-être cliquer sur Afficher tous les fichiers dans Explorateur de solutions pour consulter tous les fichiers du projet.
Compilez le projet.
Pour créer le projet de bibliothèque de classes qui se lie au modèle de types de suivi automatique
Créez un projet de bibliothèque de classes nommé STESchoolModelTypes dans la même solution que le projet précédent.
Supprimez le fichier de code source par défaut qui a été ajouté au projet.
Ajoutez un lien au fichier SchoolModel.tt afin que les types d'entité de suivi automatique soient générés dans cette solution. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur STESchoolModelTypes, cliquez sur Ajouter, puis sur Élément existant.
Dans la boîte de dialogue Ajouter un élément existant, accédez au projet STESchoolModel, puis cliquez sur SchoolModel.tt (n'appuyez pas sur Entrée). Dans la liste Ajouter, sélectionnez Ajouter en tant que lien.
Ajoutez une référence à la bibliothèque System.Runtime.Serialization. Cette bibliothèque est nécessaire pour les attributs WCF DataContract et DataMember utilisés au niveau des types d'entité sérialisable.
Compilez le projet.
Pour créer et configurer le projet d'application de service WCF
Créez un projet d'application de service WCF nommé STESchoolModelService dans la même solution que le projet précédent.
Ajoutez une référence à System.Data.Entity.dll.
Ajoutez une référence aux projets STESchoolModel et STESchoolModelTypes.
Ajoutez un lien au fichier SchoolModel.Context.tt afin que les types de contexte soient générés dans cette solution. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur STESchoolModelService, cliquez sur Ajouter, puis sur Élément existant.
Dans la boîte de dialogue Ajouter un élément existant, accédez au projet STESchoolModel, puis cliquez sur SchoolModel.Context.tt (n'appuyez pas sur Entrée). Dans la liste Ajouter, sélectionnez Ajouter en tant que lien.
Dans la fenêtre Propriétés du fichier SchoolModel.Context.tt, tapez STESchoolModelTypes dans la propriété Espace de noms de l'outil personnalisé. Le type de contexte de l'objet est alors ajouté au même espace de noms que celui des types d'entité de suivi automatique, ce qui est une condition requise.
(Visual Basic uniquement) Ajoutez
Import STESchoolModelTypes
aux fichiers sources générés à partir du fichier SchoolModel.Context.tt. Ouvrez le fichier SchoolModel.Context.tt et recherchez la chaîneImports System
. AjoutezImport STESchoolModelTypes
après d'autres importations. Les fichiers sources générés incluront cet espace de noms.Ajoutez la chaîne de connexion au fichier Web.config pour permettre au runtime Entity Framework de trouver les métadonnées. Ouvrez le fichier app.config du projet STESchoolModel . Copiez l'élémentconnectionStrings, puis ajoutez-le comme élément enfant de l'élément configuration du fichier Web.config.
Ouvrez le fichier d'interface de service. Par défaut, il s'intitule IService1.
Ajoutez l'espace de noms où sont définies les entités de suivi automatique : STESchoolModelTypes.
Remplacez la définition d'interface de service par le code suivant :
<ServiceContract()> _ Public Interface IService1 <OperationContract()> _ Sub UpdateDepartment(ByVal updated As Department) <OperationContract()> _ Function GetDepartments() As List(Of Department) End Interface
[ServiceContract] public interface IService1 { [OperationContract] void UpdateDepartment(Department updated); [OperationContract] List<Department> GetDepartments(); }
Ouvrez le code source du service. Par défaut, il est appelé Service1.srv.cs ou Service1.srv.vb.
Ajoutez l'espace de noms où sont définies les entités de suivi automatique : STESchoolModelTypes.
(Visual Basic uniquement) Ajoutez
Imports STESchoolModelService.STESchoolModelTypes
au fichier Service1.srv.cs.Remplacez la définition de classe de service par le code suivant :
Remarque : |
---|
Vous devez toujours effectuer la validation sur l'objet mis à jour avant d'appliquer les modifications. |
Public Class Service1
Implements IService1
''' <summary>
''' Updates department and its related courses.
''' </summary>
Public Sub UpdateDepartment(ByVal updated As Department) Implements IService1.UpdateDepartment
Using context As New STESchoolModelTypes.SchoolEntities()
Try
' Perform validation on the updated order before applying the changes.
' The ApplyChanges method examines the change tracking information
' contained in the graph of self-tracking entities to infer the set of operations
' that need to be performed to reflect the changes in the database.
context.Departments.ApplyChanges(updated)
context.SaveChanges()
Catch ex As UpdateException
' To avoid propagating exception messages that contain sensitive data to the client tier,
' calls to ApplyChanges and SaveChanges should be wrapped in exception handling code.
Throw New InvalidOperationException("Failed to update the department. Try your request again.")
End Try
End Using
End Sub
''' <summary>
''' Gets all the departments and related courses.
''' </summary>
Public Function GetDepartments() As List(Of Department) Implements IService1.GetDepartments
Using context As New STESchoolModelTypes.SchoolEntities()
' Use System.Data.Objects.ObjectQuery(T).Include to eagrly load the related courses.
Return context.Departments.Include("Courses").OrderBy(Function(d) d.Name).ToList()
End Using
End Function
End Class
public class Service1 : IService1
{
/// <summary>
/// Updates department and its related courses.
/// </summary>
public void UpdateDepartment(Department updated)
{
using (SchoolEntities context =
new SchoolEntities())
{
try
{
// Perform validation on the updated order before applying the changes.
// The ApplyChanges method examines the change tracking information
// contained in the graph of self-tracking entities to infer the set of operations
// that need to be performed to reflect the changes in the database.
context.Departments.ApplyChanges(updated);
context.SaveChanges();
}
catch (UpdateException ex)
{
// To avoid propagating exception messages that contain sensitive data to the client tier,
// calls to ApplyChanges and SaveChanges should be wrapped in exception handling code.
throw new InvalidOperationException("Failed to update the department. Try your request again.");
}
}
}
/// <summary>
/// Gets all the departments and related courses.
/// </summary>
public List<Department> GetDepartments()
{
using (SchoolEntities context = new SchoolEntities())
{
// Use System.Data.Objects.ObjectQuery(T).Include to eagrly load the related courses.
return context.Departments.Include("Courses").OrderBy(d => d.Name).ToList();
}
}
}
Pour tester le service avec une application cliente console
Créez une application console. Tapez STESchoolModelTest comme nom de projet dans la même solution que le projet précédent.
Ajoutez une référence au service STEASchoolModelService. Pour ajouter une référence au service, dans l'Explorateur de solutions, cliquez avec le bouton droit sur le dossier de référence, puis sélectionnez Ajouter une référence de service.
Par défaut, WCF génère un proxy qui retourne la collection IEnumerable. Comme la méthode GetDepartments de STESchoolModelService retourne List, vous devez configurer le service pour spécifier le type de retour approprié.
Cliquez avec le bouton droit sur le nom du service (ServiceReference1), puis sélectionnez Configurer la référence de service.... Dans la boîte de dialogue Configurer la référence de service, sélectionnez le type System.Collections.Generic.List dans la liste Type de collection.
Ajoutez une référence au projet STESchoolModelTypes .
Ouvrez le fichier app.config, puis ajoutez la chaîne de connexion au fichier. Ouvrez le fichier app.config des projets STESchoolModel, puis copiez l'élément connectionStrings pour l'ajouter comme élément enfant de l'élément configuration du fichier Web.config.
Ouvrez le fichier qui contient la fonction principale. Incluez les espaces de noms suivants : STESchoolModelTest.ServiceReference1 et les espaces de noms STESchoolModelTypes (où sont définis les types de suivi automatique).
Collez le code suivant dans votre fonction principale. Le code contient des appels de fonction aux méthodes définies dans l'étape suivante.
' Note, the service's GetDepartments method returns System.Collections.Generic.List. ' By default, when WCF generates a proxy the return collection types are converted to IEnumerable. ' The WCF service has to be configured to specify the List return type. ' To specify the List collection type, open the Configure Service Reference dialog and ' select the System.Collections.Generic.List type from the Collection type list. Console.WriteLine("See the existing departments and courses.") DisplayDepartmentsAndCourses() Console.WriteLine() Console.WriteLine() ' Use some IDs to create ' new Department and Course. ' The newly created objects will ' be then deleted. Dim departmentID As Integer = 100 Dim courseID As Integer = 50 AddNewDepartmentAndCourses(departmentID, courseID) Console.WriteLine("See existing and added.") DisplayDepartmentsAndCourses() Console.WriteLine() UpdateDepartmentAndCourses(departmentID, courseID) Console.WriteLine("See existing and updated.") DisplayDepartmentsAndCourses() Console.WriteLine() DeleteDepartmentAndCourses(departmentID)
// Note, the service's GetDepartments method returns System.Collections.Generic.List. // By default, when WCF generates a proxy the return collection types are converted to IEnumerable. // The WCF service has to be configured to specify the List return type. // To specify the List collection type, open the Configure Service Reference dialog and // select the System.Collections.Generic.List type from the Collection type list. Console.WriteLine("See the existing departments and courses."); DisplayDepartmentsAndCourses(); Console.WriteLine(); Console.WriteLine(); // Use some IDs to create // new Department and Course. // The newly created objects will // be then deleted. int departmentID = 100; int courseID = 50; AddNewDepartmentAndCourses(departmentID, courseID); Console.WriteLine("See existing and added."); DisplayDepartmentsAndCourses(); Console.WriteLine(); UpdateDepartmentAndCourses(departmentID, courseID); Console.WriteLine("See existing and updated."); DisplayDepartmentsAndCourses(); Console.WriteLine(); DeleteDepartmentAndCourses(departmentID);
Ajoutez les méthodes suivantes à la classe. Les méthodes vous indiquent comment effectuer les opérations suivantes : afficher les objets retournés par le service, ajouter de nouveaux objets, mettre à jour des objets et supprimer des objets. Pour plus d'informations, consultez les commentaires du code.
Private Sub DisplayDepartmentsAndCourses() Using service = New Service1Client() ' Get all the departments. Dim departments As List(Of Department) = service.GetDepartments() For Each d In departments Console.WriteLine("ID: {0}, Name: {1}", d.DepartmentID, d.Name) ' Get all the courses for each department. ' The reason we are able to access ' the related courses is because the service eagrly loaded the related objects ' (using the System.Data.Objects.ObjectQuery(T).Include method). For Each c In d.Courses.OfType(Of OnlineCourse)() Console.WriteLine(" OnLineCourse ID: {0}, Title: {1}", c.CourseID, c.Title) Next For Each c In d.Courses.OfType(Of OnsiteCourse)() Console.WriteLine(" OnSiteCourse ID: {0}, Title: {1}", c.CourseID, c.Title) Next Next End Using End Sub Private Sub AddNewDepartmentAndCourses(ByVal departmentID As Integer, ByVal courseID As Integer) Using service = New Service1Client() Dim newDepartment As New Department() _ With {.DepartmentID = departmentID, _ .Budget = 13000D, _ .Name = "New Department", _ .StartDate = DateTime.Now _ } Dim newCourse As New OnlineCourse() _ With {.CourseID = courseID, _ .DepartmentID = departmentID, _ .URL = "http://www.fineartschool.net/Trigonometry", _ .Title = "New Onsite Course", _ .Credits = 4 _ } ' Add the course to the department. newDepartment.Courses.Add(newCourse) ' The newly create objects are marked as added, the service will insert these into the store. service.UpdateDepartment(newDepartment) ' Let’s make few more changes to the saved object. ' Since the previous changes have now been persisted, call AcceptChanges to ' reset the ChangeTracker on the objects and mark the state as ObjectState.Unchanged. ' Note, AcceptChanges sets the tracking on, so you do not need to call StartTracking ' explicitly. newDepartment.AcceptChanges() newCourse.AcceptChanges() ' Because the change tracking is enabled ' the following change will set newCourse.ChangeTracker.State to ObjectState.Modified. newCourse.Credits = 6 service.UpdateDepartment(newDepartment) End Using End Sub Private Sub UpdateDepartmentAndCourses(ByVal departmentID As Integer, ByVal courseID As Integer) Using service = New Service1Client() ' Get all the departments. Dim departments As List(Of Department) = service.GetDepartments() ' Use LINQ to Objects to query the departments collection ' for the specific department object. Dim department As Department = departments.Single(Function(d) d.DepartmentID = departmentID) department.Budget = department.Budget - 1000D ' Get the specified course that belongs to the department. ' The reason we are able to access the related course ' is because the service eagrly loaded the related objects ' (using the System.Data.Objects.ObjectQuery(T).Include method). Dim existingCourse As Course = department.Courses.[Single](Function(c) c.CourseID = courseID) existingCourse.Credits = 3 service.UpdateDepartment(department) End Using End Sub Private Sub DeleteDepartmentAndCourses(ByVal departmentID As Integer) Using service = New Service1Client() Dim departments As List(Of Department) = service.GetDepartments() Dim department As Department = departments.Single(Function(d) d.DepartmentID = departmentID) ' When MarkAsDeleted is called, the entity is removed from the collection, ' if we modify the collection over which foreach is looping an exception will be thrown. ' That is why we need to make a copy of the courses collection by ' calling department.Courses.ToList(); Dim courses As List(Of Course) = department.Courses.ToList() For Each c In courses ' Marks each comment for the post as Deleted. ' If another entity have a foreign key relationship with this Course object ' an exception will be thrown during save operation. c.MarkAsDeleted() Next department.MarkAsDeleted() service.UpdateDepartment(department) End Using End Sub
static void DisplayDepartmentsAndCourses() { using (var service = new Service1Client()) { // Get all the departments. List<Department> departments = service.GetDepartments(); foreach (var d in departments) { Console.WriteLine("ID: {0}, Name: {1}", d.DepartmentID, d.Name); // Get all the courses for each department. // The reason we are able to access // the related courses is because the service eagrly loaded the related objects // (using the System.Data.Objects.ObjectQuery(T).Include method). foreach (var c in d.Courses.OfType<OnlineCourse>()) { Console.WriteLine(" OnLineCourse ID: {0}, Title: {1}", c.CourseID, c.Title); } foreach (var c in d.Courses.OfType<OnsiteCourse>()) { Console.WriteLine(" OnSiteCourse ID: {0}, Title: {1}", c.CourseID, c.Title); } } } } static void AddNewDepartmentAndCourses(int departmentID, int courseID) { using (var service = new Service1Client()) { Department newDepartment = new Department() { DepartmentID = departmentID, Budget = 13000.000m, Name = "New Department", StartDate = DateTime.Now }; OnlineCourse newCourse = new OnlineCourse() { CourseID = courseID, DepartmentID = departmentID, URL = "http://www.fineartschool.net/Trigonometry", Title = "New Onsite Course", Credits = 4 }; // Add the course to the department. newDepartment.Courses.Add(newCourse); // The newly create objects are marked as added, the service will insert these into the store. service.UpdateDepartment(newDepartment); // Let’s make few more changes to the saved object. // Since the previous changes have now been persisted, call AcceptChanges to // reset the ChangeTracker on the objects and mark the state as ObjectState.Unchanged. // Note, AcceptChanges sets the tracking on, so you do not need to call StartTracking // explicitly. newDepartment.AcceptChanges(); newCourse.AcceptChanges(); // Because the change tracking is enabled // the following change will set newCourse.ChangeTracker.State to ObjectState.Modified. newCourse.Credits = 6; service.UpdateDepartment(newDepartment); } } static void UpdateDepartmentAndCourses(int departmentID, int courseID) { using (var service = new Service1Client()) { // Get all the departments. List<Department> departments = service.GetDepartments(); // Use LINQ to Objects to query the departments collection // for the specific department object. Department department = departments.Single(d => d.DepartmentID == departmentID); department.Budget = department.Budget - 1000.00m; // Get the specified course that belongs to the department. // The reason we are able to access the related course // is because the service eagrly loaded the related objects // (using the System.Data.Objects.ObjectQuery(T).Include method). Course existingCourse = department.Courses.Single(c => c.CourseID == courseID); existingCourse.Credits = 3; service.UpdateDepartment(department); } } static void DeleteDepartmentAndCourses(int departmentID) { using (var service = new Service1Client()) { List<Department> departments = service.GetDepartments(); Department department = departments.Single(d => d.DepartmentID == departmentID); // When MarkAsDeleted is called, the entity is removed from the collection, // if we modify the collection over which foreach is looping an exception will be thrown. // That is why we need to make a copy of the courses collection by // calling department.Courses.ToList(); List<Course> courses = department.Courses.ToList(); foreach (var c in courses) { // Marks each comment for the post as Deleted. // If another entity have a foreign key relationship with this Course object // an exception will be thrown during save operation. c.MarkAsDeleted(); } department.MarkAsDeleted(); service.UpdateDepartment(department); } }
Pour tester le service avec une application cliente WPF
Créez une application WPF. Tapez STESchoolModelWPFTest comme nom de projet dans la même solution que le projet précédent.
Ajoutez une référence au service STEASchoolModelService. Pour ajouter une référence au service, dans l'Explorateur de solutions, cliquez avec le bouton droit sur le dossier de référence, puis sélectionnez Ajouter une référence de service.
Par défaut, WCF génère un proxy qui retourne la collection IEnumerable. Comme la méthode GetDepartments de STESchoolModelService retourne List, vous devez configurer le service pour spécifier le type de retour approprié.
Cliquez avec le bouton droit sur le nom du service (ServiceReference1), puis sélectionnez Configurer la référence de service.... Dans la boîte de dialogue Configurer la référence de service, sélectionnez le type System.Collections.Generic.List dans la liste Type de collection.
Ajoutez une référence au projet STESchoolModelTypes .
Ouvrez le fichier app.config, puis ajoutez la chaîne de connexion au fichier. Ouvrez le fichier app.config des projets STESchoolModel, puis copiez l'élément connectionStrings pour l'ajouter comme élément enfant de l'élément configuration du fichier Web.config.
Vous pouvez maintenant supprimer le fichier app.config pour le projet STESchoolModel parce qu'il n'est jamais utilisé.
Par défaut, le modèle de projet ajoute au projet le fichier MainWindow.xaml et le fichier code-behind correspondant.
Ouvrez le fichier MainWindow.xaml, puis remplacez le code XAML par défaut par le code XAML qui définit la fenêtre STESchoolModelWPFTest dans WPF. Pour plus d'informations, consultez les commentaires du code.
<Window x:Class="STESchoolModelWPFTest.MainWindow" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="508" Width="919" Loaded="Window_Loaded"> <!-- The code begind code sets the departmentsItemsGrid to the root of the object graph.--> <Grid Name="departmentsItemsGrid"> <!-- comboBoxDepartment points to the root of the graph, that is why the Path is not specified--> <ComboBox DisplayMemberPath="DepartmentID" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="true" Height="23" Margin="122,12,198,0" Name="comboBoxDepartment" VerticalAlignment="Top"/> <!-- listViewItems Path is set to Courses because it is bound to Department.Courses.--> <ListView ItemsSource="{Binding Path=Courses}" Name="listViewItems" Margin="34,46,34,50" > <ListView.View> <GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Courses" > <GridViewColumn DisplayMemberBinding="{Binding Path=CourseID}" Header="CourseID" Width="70"/> <!--The TextBox controls are embedded in the two of the following columns. This is done to enable editing in the ListView control. --> <GridViewColumn Header="Title" Width="100"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBox Height="25" Width="100" Text="{Binding Path=Title}" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn Header="Credits" Width="100" > <GridViewColumn.CellTemplate> <DataTemplate> <TextBox Height="25" Width="100" Text="{Binding Path=Credits}" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> </GridView> </ListView.View> </ListView> <Label Height="28" Margin="34,12,0,0" Name="departmentLabel" VerticalAlignment="Top" HorizontalAlignment="Left" Width="93">Department:</Label> <!--When the Save and Close button is clicked all the objects will be sent to the service where all the updated objects will be saved to the database. --> <Button Height="23" HorizontalAlignment="Right" Margin="0,0,34,12" Name="buttonClose" VerticalAlignment="Bottom" Width="127" Click="buttonClose_Click">Save and Close</Button> </Grid> </Window>
Ouvrez le fichier MainWindow.xaml.cs (ou .vb), puis remplacez le code-behind par défaut par le code suivant (consultez les commentaires du code pour plus d'explication).
Class MainWindow Dim departments As List(Of Department) Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded Using service = New Service1Client() ' Set the parent of of your data bound controls to the root of the graph. ' In the xaml page the appropriate paths should be set on each data bound control. ' For the comboBoxDepartment it is empty because it is bound to Departments (which is root). ' For the listViewItems it is set to Courses because it is bound to Department.Courses. ' Note, that the TextBox controls are embedded in the two of the columns in the listViewItems. ' This is done to enable editing in the ListView control. departments = service.GetDepartments() Me.departmentsItemsGrid.DataContext = departments End Using End Sub Private Sub buttonSave_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles buttonSave.Click Using service = New Service1Client() ' Save all the departments and their courses. For Each department In departments service.UpdateDepartment(department) ' Call AcceptChanges on all the objects ' to resets the change tracker and set the state of the objects to Unchanged. department.AcceptChanges() For Each course In department.Courses course.AcceptChanges() Next Next End Using End Sub Private Sub buttonClose_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles buttonClose.Click ' Close the form. Me.Close() End Sub End Class
public partial class MainWindow : Window { private List<Department> departments; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { using (var service = new Service1Client()) { // Set the parent of of your data bound controls to the root of the graph. // In the xaml page the appropriate paths should be set on each data bound control. // For the comboBoxDepartment it is empty because it is bound to Departments (which is root). // For the listViewItems it is set to Courses because it is bound to Department.Courses. // Note, that the TextBox controls are embedded in the two of the columns in the listViewItems. // This is done to enable editing in the ListView control. departments = service.GetDepartments(); this.departmentsItemsGrid.DataContext = departments; } } private void buttonSave_Click(object sender, RoutedEventArgs e) { using (var service = new Service1Client()) { // Save all the departments and their courses. foreach (var department in departments) { service.UpdateDepartment(department); // Call AcceptChanges on all the objects // to resets the change tracker and set the state of the objects to Unchanged. department.AcceptChanges(); foreach (var course in department.Courses) course.AcceptChanges(); } } } private void buttonClose_Click(object sender, RoutedEventArgs e) { //Close the form. this.Close(); } }
Voir aussi
Concepts
Utilisation des entités de suivi automatique
Sérialisation d'objets (Entity Framework)
Génération d'applications multicouches (Entity Framework)