Condividi tramite


Procedura dettagliata: serializzazione di entità con rilevamento automatico (Entity Framework)

La procedura dettagliata di questo argomento illustra lo scenario nel quale un servizio WCF (Windows Communication Foundation) espone una serie di operazioni che restituiscono grafici di entità. Successivamente un'applicazione client modifica il grafico e inoltra le modifiche a un'operazione del servizio che convalida e salva gli aggiornamenti in un database utilizzando Entity Framework. Per ulteriori informazioni, vedere Utilizzo delle entità con rilevamento automatico.

Generalmente si preferisce separare il progetto modello dal progetto che contiene i tipi di entità con rilevamento automatico. Il client dovrà quindi includere solo il progetto dei tipi di entità.

Un modo per ottenere questo isolamento consiste nel separare i tipi di entità con rilevamento automatico dal modello e spostare il modello mediante il quale vengono generati i tipi di entità in una libreria di classi separata. Per poter accedere ai metadati, il percorso del file con estensione edmx dovrà essere incluso nel modello di entità con rilevamento automatico. Se si spostano i modelli dal progetto originale in altri progetti, è necessario aprire i file del modello in un editor e modificare la stringa inputFile nel percorso relativo del file con estensione edmx. Per ulteriori informazioni sull'utilizzo dei modelli, vedere ADO.NET Self-Tracking Entity Template.

Un altro modo per separare i tipi di entità dal modello consiste nel lasciare i file del modello nel progetto originale, disabilitando però la generazione di codice per i modelli. Collegarsi ai modelli da un altro progetto, in modo che il codice venga generato in tale progetto anziché in quello originale. Quando si aggiunge un elemento a un progetto come collegamento, il contenuto effettivo dell'elemento viene gestito nel percorso indicato dal progetto originale. In questa procedura dettagliata verrà illustrato questo metodo di separazione dei tipi di entità dal modello.

In questa procedura dettagliata verranno completate le azioni seguenti:

  • Verrà creato il progetto della libreria di classi che contiene il modello basato su School.

  • Verrà utilizzato il modello Generatore di entità con rilevamento automatico ADO.NET per generare i tipi di entità, l'oggetto ObjectContext tipizzato e una classe delle estensioni contenente i metodi ApplyChanges di overload.

  • Verrà creato il progetto della libreria di classi che si collega al modello dei tipi di entità con rilevamento automatico creato nel primo progetto.

  • Verrà creato il servizio WCF, che espone un set di operazioni che consentono di restituire grafici di entità e di applicare le modifiche apportate sul client al database tramite Entity Framework .

  • Verrà creata l'applicazione client (console e WPF, Windows Presentation Foundation) che consente di modificare il grafico e di inoltrare le modifiche tramite le operazioni esposte nel servizio WCF.

Ee789839.note(it-it,VS.100).gifNota:
È possibile scaricare STESchoolModelExample nel sito Entity Framework Documentation Samples su MSDN Code Gallery.

Per creare il progetto della libreria di classi che contiene le entità con rilevamento automatico e le classi del contesto dell'oggetto

  1. Creare un nuovo progetto della libreria di classi. Digitare STESchoolModel per il nome della soluzione e del progetto.

  2. Rimuovere il file di codice sorgente predefinito aggiunto al progetto.

  3. Utilizzare la Procedura guidata Entity Data Model per generare un modello basato sulle tabelle Department, Course, OnlineCourse e OnsiteCourse del database School. Per ulteriori informazioni, vedere Modello School.

  4. Aprire il file con estensione edmx in ADO.NET Entity Data Model Designer (Entity Designer).

  5. Seguire le istruzioni sull'ereditarietà del mapping nell'argomento Walkthrough: Mapping Inheritance - Table-per-Type.

  6. Fare clic con il pulsante destro del mouse in un'area vuota di Entity Designer, scegliere Aggiungi elemento di generazione codice, quindi selezionare Generatore di entità con rilevamento automatico ADO.NET. Impostare il nome del modello predefinito su SchoolModel.

    Ee789839.note(it-it,VS.100).gifNota:
    Quando i file del modello vengono aggiunti al progetto, è possibile che venga visualizzato un avviso di sicurezza in cui viene chiesto di accettare solo se si considera attendibile l'origine del modello.Fare clic su Accetta.

  7. Le cartelle SchoolModel.Context.tt e SchoolModel.tt vengono aggiunte al progetto. Nella cartella SchoolModel.Context.tt sono disponibili due file in cui vengono definiti l'oggetto ObjectContext tipizzato e la classe delle estensioni contenente i metodi ApplyChanges di overload. Nella cartella SchoolModel.tt sono invece disponibili i file in cui vengono definiti i tipi di entità e una classe di supporto che contiene la logica di rilevamento delle modifiche utilizzata dalle entità con rilevamento automatico.

    I due passaggi successivi illustrano la disabilitazione della generazione di codice in questo progetto. La generazione di codice verrà successivamente abilitata per i tipi nella libreria di classi STESchoolModelTypes e per il contesto dell'oggetto in STESchoolModelService.

  8. Selezionare SchoolModel.tt. Nella finestra Proprietà cancellare TextTemplatingFileGenerator dalla proprietà CustomTool. Eliminare i file nella cartella SchoolModel.tt.

  9. Selezionare SchoolModel.Context.tt. Nella finestra Proprietà cancellare il valore della proprietà CustomTool. Eliminare i file nella cartella SchoolModel.Context.tt.

    Se si utilizza il progetto Visual Basic, potrebbe essere necessario fare clic su Mostra tutti i file in Esplora soluzioni per vedere tutti i file del progetto.

  10. Compilare il progetto.

Per creare il progetto della libreria di classi che si collega al modello dei tipi con rilevamento automatico

  1. Creare un nuovo progetto della libreria di classi denominato STESchoolModelTypes nella stessa soluzione del progetto precedente.

  2. Rimuovere il file di codice sorgente predefinito aggiunto al progetto.

  3. Aggiungere un collegamento al file SchoolModel.tt in modo che in questa soluzione vengano generati i tipi di entità con rilevamento automatico. In Esplora soluzioni fare clic con il pulsante destro del mouse su STESchoolModelTypes, scegliere Aggiungi, quindi fare clic su Elemento esistente.

  4. Nella finestra di dialogo Aggiungi elemento esistente accedere al progetto STESchoolModel e fare clic su SchoolModel.tt (non premere INVIO). Nell'elenco Aggiungi selezionare Aggiungi come collegamento.

  5. Aggiungere un riferimento alla libreria System.Runtime.Serialization. Questa libreria è necessaria per gli attributi DataContract e DataMember di WCF utilizzati sui tipi di entità serializzabili.

  6. Compilare il progetto.

Per creare e configurare il progetto Applicazione di servizi WCF

  1. Creare un progetto Applicazione di servizi WCF denominato STESchoolModelService nella stessa soluzione del progetto precedente.

  2. Aggiungere un riferimento a System.Data.Entity.dll.

  3. Aggiungere un riferimento ai progetti STESchoolModel e STESchoolModelTypes.

  4. Aggiungere un collegamento al file SchoolModel.Context.tt in modo che i tipi di contesto vengano generati in questa soluzione. In Esplora soluzioni fare clic con il pulsante destro del mouse su STESchoolModelService, scegliere Aggiungi, quindi fare clic su Elemento esistente.

  5. Nella finestra di dialogo Aggiungi elemento esistente selezionare il progetto STESchoolModel e fare clic su SchoolModel.Context.tt (non premere INVIO). Nell'elenco Aggiungi selezionare Aggiungi come collegamento.

  6. Nella finestra Proprietà per il file SchoolModel.Context.tt digitare STESchoolModelTypes nella proprietà Spazio dei nomi dello strumento personalizzato. In questo modo il tipo di contesto dell'oggetto viene aggiunto allo stesso spazio dei nomi dello spazio dei nomi, richiesto, per i tipi di entità con rilevamento automatico.

  7. (Solo Visual Basic) Aggiungere Import STESchoolModelTypes ai file di origine generati dal file SchoolModel.Context.tt. Aprire il file SchoolModel.Context.tt e individuare la stringa Imports System. Aggiungere Import STESchoolModelTypes dopo altre importazioni. I file di origine generati includeranno questo spazio dei nomi.

  8. Aggiungere la stringa di connessione al file Web.config in modo che mediante il runtime di Entity Framework sia possibile trovare i metadati. Aprire il file app.config del progetto STESchoolModel . Copiare l'elemento connectionStrings, quindi aggiungerlo come figlio dell'elemento configuration del file Web.config.

  9. Aprire il file di interfaccia di servizio. Per impostazione predefinita, si tratta di IService1.

  10. Aggiungere lo spazio dei nomi in cui sono definite le entità con rilevamento automatico: STESchoolModelTypes.

  11. Sostituire la definizione dell'interfaccia di servizio con il codice riportato di seguito:

    <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();
    }
    
  12. Aprire il codice sorgente del servizio. Per impostazione predefinita, si tratta di Service1.srv.cs o Service1.srv.vb.

  13. Aggiungere lo spazio dei nomi in cui sono definite le entità con rilevamento automatico: STESchoolModelTypes.

  14. (Solo Visual Basic) Aggiungere Imports STESchoolModelService.STESchoolModelTypes al file Service1.srv.cs.

  15. Sostituire la definizione delle classi di servizio con il codice seguente:

Ee789839.Important(it-it,VS.100).gif Nota:
È necessario eseguire sempre la convalida sull'oggetto aggiornato prima di applicare le modifiche.

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

}

Per verificare il funzionamento del servizio con un'applicazione client console

  1. Creare un'applicazione console. Digitare STESchoolModelTest come nome di progetto nella stessa soluzione del progetto precedente.

  2. Aggiungere un riferimento al servizio STEASchoolModelService. Per aggiungere un riferimento al servizio, fare clic con il pulsante destro del mouse sulla cartella di riferimento in Esplora soluzioni e scegliere Aggiungi riferimento al servizio.

    Per impostazione predefinita, WCF genera un proxy che restituisce la raccolta IEnumerable. Poiché il metodo STESchoolModelService's GetDepartments restituisce List, è necessario configurare il servizio per specificare il tipo restituito appropriato.

  3. Fare clic con il pulsante destro del mouse sul nome del servizio (ServiceReference1) e scegliere Configura riferimento al servizio. Nella finestra di dialogo Configura riferimento al servizio selezionare il tipo System.Collections.Generic.List nell'elenco Tipo di raccolta.

  4. Aggiungere un riferimento al progetto STESchoolModelTypes .

  5. Aprire il file app.config e quindi aggiungere la stringa di connessione al file. Aprire il file app.config dei progetti STESchoolModel e quindi copiare l'elemento connectionStrings per aggiungerlo come figlio dell'elemento configuration del file Web.config.

  6. Aprire il file che contiene la funzione principale. Includere gli spazi dei nomi seguenti: STESchoolModelTest.ServiceReference1 e STESchoolModelTypes (in cui sono definiti i tipi con rilevamento automatico).

  7. Incollare il codice seguente nella funzione principale. Il codice contiene chiamate di funzione ai metodi definiti nel passaggio successivo.

    ' 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);
    
  8. Aggiungere i metodi seguenti alla classe. I metodi mostrano come eseguire le operazioni seguenti: visualizzare gli oggetti restituiti dal servizio, aggiungere nuovi oggetti e aggiornare ed eliminare oggetti esistenti. Per ulteriori informazioni, vedere i commenti del codice.

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

Per verificare il funzionamento del servizio con un'applicazione client WPF

  1. Creare un'applicazione WPF. Digitare STESchoolModelWPFTest come nome di progetto nella stessa soluzione del progetto precedente.

  2. Aggiungere un riferimento al servizio STEASchoolModelService. Per aggiungere un riferimento al servizio, fare clic con il pulsante destro del mouse sulla cartella di riferimento in Esplora soluzioni e scegliere Aggiungi riferimento al servizio.

    Per impostazione predefinita, WCF genera un proxy che restituisce la raccolta IEnumerable. Poiché il metodo STESchoolModelService's GetDepartments restituisce List, è necessario configurare il servizio per specificare il tipo restituito appropriato.

  3. Fare clic con il pulsante destro del mouse sul nome del servizio (ServiceReference1) e scegliere Configura riferimento al servizio. Nella finestra di dialogo Configura riferimento al servizio selezionare il tipo System.Collections.Generic.List nell'elenco Tipo di raccolta.

  4. Aggiungere un riferimento al progetto STESchoolModelTypes .

  5. Aprire il file app.config e quindi aggiungere la stringa di connessione al file. Aprire il file app.config dei progetti STESchoolModel e quindi copiare l'elemento connectionStrings per aggiungerlo come figlio dell'elemento configuration del file Web.config.

    È possibile ora eliminare il file app.config per il progetto STESchoolModel in quanto non viene mai utilizzato.

    Per impostazione predefinita, il modello di progetto aggiunge il file MainWindow.xaml e il file code-behind corrispondente al progetto.

  6. Aprire il file MainWindow.xaml, quindi sostituire il codice XAML predefinito con il codice XAML che definisce la finestra STESchoolModelWPFTest in WPF. Per ulteriori informazioni, vedere i commenti del codice.

    <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>
    
  7. Aprire il file MainWindow.xaml.cs (o con estensione vb), quindi sostituire il code-behind predefinito con il codice seguente (per una spiegazione più approfondita, vedere i commenti del codice).

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

Vedere anche

Concetti

Utilizzo delle entità con rilevamento automatico
Serializzazione di oggetti (Entity Framework)
Compilazione di applicazioni a più livelli (Entity Framework)

Altre risorse

ADO.NET Self-Tracking Entity Template