Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1909, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Disabilita cookie ShinyStat

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Xamarin Certified Mobile Developer

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

GitHub
I miei progetti open-source su GitHub

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

Rappresentazioni Master-Details in Windows Forms con VB 2008 ed Entity Framework

Se avete letto il mio articolo introduttivo a LINQ-to-SQL, o se avete acquistato il mio libro su LINQ in Visual Basic 2008, avete visto come sia semplice creare una basilare applicazione Windows Forms in grado di soddisfare l’esigenza di creare finestre che espongano, attraverso l’interfaccia, relazioni one-to-many tra entità attraverso rappresentazioni di tipo master-detail.

 

Il tutto avviene, sostanzialmente, sfruttando alcuni automatismi di Microsoft Visual Studio 2008 che ci consentono di fare il drag’n’drop di oggetti rappresentanti le entità dalla finestra Data Sources sul form di nostro interesse. L’IDE genera poi i controlli necessari, si occupa del data-binding e l’unica cosa che noi dobbiamo fare da codice è specificare la sorgente dati per la parte “one” della relazione.

 

Purtroppo questo non avviene se lavoriamo con ADO.NET Entity Framework (introdotto, come ricordate, da .NET Framework 3.5 Service Pack 1), ossia il drag’n’drop e la specifica di una sola sorgente dati non sono sufficienti ad ottenere lo stesso risultato avuto in LINQ-to-SQL, in quanto la seconda sorgente dati non è collegata automaticamente alla prima e la visualizzazione dei “detail” non avviene affatto.

 

Come si fa allora, se avessimo bisogno di fare una cosa simile (per quanto semplice) con l’Entity Framework? Ho risolto il problema grazie alle indicazioni di Ken Tucker, Microsoft Visual Basic MVP, che mi ha messo sulla strada giusta.

 

Supponiamo di voler creare un’applicazione Windows Forms in grado di mostrare i c.d. tabular data, attraverso due DataGridView, il contenuto delle tabelle Categories e Products del database Northwind e che, alla selezione di ciascuna categoria, vengano mostrati nella seconda griglia i prodotti correlati. In LINQ-to-SQL il risultato si ottiene con pochi passaggi, illustrati nell’articolo sopra citato.

 

Lavorando con l’Entity Framework, bisogna ricorrere a una tecnica definita eager loading che si pone in essere attraverso un metodo chiamato Include. In primo luogo, si agisce in questo modo:

 

1.    si crea il progetto Windows Forms con Visual Basic 2008;

2.    si stabilisce la connessione al database e si aggiunge al progetto un nuovo Entity Data Model (per un primo contatto con l’EDM, leggi qui);

3.    si aggiungono all’EDM le tabelle desiderate, relazionate tra loro. Nell’esempio seguente faremo riferimento alle Categories e Products di Northwind;

4.    si aggiunge una nuova origine dati (comando Data|Add New Data Source) che punti all’oggetto Categories generato dalla procedura di mapping.

 

La finestra Data Sources dovrebbe presentarsi così:

 

 

 

A questo punto non ci resta che eseguire il drag’n’drop dei due oggetti (Categories e Products) sul form affinchè Visual Studio generi comunque i controlli dell’interfaccia, il cui aspetto diventa il seguente:

 

 

Ora dobbiamo passare al codice Visual Basic. Come detto, a differenza di quanto avevamo visto in LINQ-to-SQL, non possiamo semplicemente assegnare la collection Categories (o una query formulata su di essa con LINQ) alla proprietà DataSource del BindingSource (CategoriesBindingSource), che Visual Studio ha generato automaticamente, affinché, di riflesso, il controllo ProductsBindingSource si aggiorni per mostrare i prodotti (quindi i “detail”) della categoria selezionata.

 

Ciò premesso, passando all’editor di codice, in primo luogo istanziamo l’ObjectContext:

 

    Private NorthwindContext As New NorthwindEntities

 

Fatto questo, in primo luogo specifichiamo l’origine dati per la parte “master”. Ho aggiunto specifici commenti nel codice:

 

        'Il metodo Include mi permette di inglobare anche gli oggetti relazionati

        Dim dataSource = NorthwindContext.Categories.Include("Products")

 

        'L'origine dati primaria rimane comunque Categories

        CategoriesBindingSource.DataSource = dataSource

 

Quindi, grazie al metodo Include, carichiamo anche la parte dei “detail” (eager loading), della quale ci occupiamo nelle righe che vanno digitate di seguito:

 

        'L'origine dati per i Products è il controllo CategoriesBindingSource

        'che contiene sia le categorie che i prodotti...

        ProductsBindingSource.DataSource = CategoriesBindingSource

 

        '...del quale posso visualizzare la sola collezione che mi interessa

        'mediante la proprietà DataMember che punta al nome della collezione stessa

        ProductsBindingSource.DataMember = "Products"

 

In effetti, questo tipo di situazione ha un limite, nel senso che l'utilizzo di una stringa fa perdere parte importante dell'essenza di LINQ, ossia il trattamento di oggetti in ottica fortemente tipizzata. Un'alternativa è stata proposta, attualmente in Visual C#, da Mattheiu Mezil (Microsoft MVP) nel suo blog, per poter utilizzare un'espressione lambda. Potete dare un'occhiata, ma c'è da eseguire la conversione in Visual Basic (mi ci metterò d'impegno :-)).

 

Se ora avviamo l’applicazione, ci basterà selezionare le varie righe della DataGridView relativa alle categorie per vedere i corrispondenti dettagli nella griglia sottostante relativa ai prodotti:

 

 

 

Ovviamente, questo basta per la visualizzazione dei dati. Se volessimo però aggiungere nuovi prodotti, dobbiamo assegnare esplicitamente la proprietà AllowNew dell’oggetto ProductsBindingSource perchè, al contrario di LINQ-to-SQL, nell’Entity Framework questa non è un’impostazione di default. Perciò, di seguito al codice precedente, è sufficiente aggiungere la seguente riga:

 

        ProductsBindingSource.AllowNew = True

 

Cosa che non serve per le Categories. Possiamo infine prevedere, nella sua espressione più semplice e basilare, un metodo per persistere i dati nel database. Dopo aver abilitato il pulsante di salvataggio sul BindingNavigator, possiamo gestirne il relativo evento Click:

 

    Private Sub CategoriesBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CategoriesBindingNavigatorSaveItem.Click

 

        Try

            NorthwindContext.SaveChanges()

 

        Catch ex As Exception

 

            MessageBox.Show("An error has occurred while saving changes to the database")

        End Try

    End Sub

 

And that’s all. Potete scaricare il progetto sorgente completo relativo a questa piccola demo a questo indirizzo dell’area Download di Visual Basic Tips & Tricks. All’interno dello zip troverete anche un installer in formato .Vsi (creato col nostro Vsi Builder 2008) che vi permetterà di installare un code snippet riutilizzabile in Visual Studio 2008 e che include il codice relativo alla gestione del binding master-details sopra illustrato.

 

Alessandro

Print | posted on venerdì 14 novembre 2008 22:56 | Filed Under [ .NET Framework Visual Basic Visual Studio 2008 LINQ ]

Powered by:
Powered By Subtext Powered By ASP.NET