Antonio "tdj"

(C'è sempre un modo migliore)
posts - 294, comments - 285, trackbacks - 17

My Links

News







Tag Cloud

Article Categories

Archives

Post Categories

Image Galleries

Articoli

Blogs

Controlli WinForm free

Guide

Siti vari

Sviluppo

lunedì 30 aprile 2012

EF Code First: <Key> e <ForeignKey>

Gli attributi <Key> e <ForeignKey> sono utilizzati da Entity Framework Code First per definire rispettivamente la (o le) chiave primaria e la chiave esterna qualora non sia (o non si voglia) seguire la “naming convention”.

L’attributo <Key> è intuitivo, serve per marcare una o più proprietà come chiave primaria nel database. Consideriamo le seguenti entità:

   Public Class Book
<Key()>
Property BookId As Integer
Property Title As String
Property Author As Author  
End Class

   Public Class Author    
       Property AuthorId As Integer
       Property FirstName As String
       Property LastName As String
End Class

 

il risultato nel database è il seguente:

 

image

 

Tutto nella norma per quanto riguarda la chiave BookId mentre la chiave esterna rappresentata dalla proprietà Author è stata tradotta nel database con la coppia PropertyNavigationName_PropertyNameId che nell’esempio è Author_AuthorId. Si tratta di una convenzioni usata da Entity Framework laddove non viene specificato nulla dall’utente.

Ma se volessimo avere anche il valore della chiave esterna oltre all’intero oggetto rappresentato dalla navigation property Author, esattamente come avviene in Entity Framework 4? Usiamo l’attributo <ForeignKey> modificando la classe Book in questo modo:

 

   Public Class Book
     <Key()>
     Property BookId As Integer
     Property Title As String
     <ForeignKey("AuthorId")>
     Property Author As Author        Property AuthorId As Integer
   End 
Class


Semplicemente si aggiunge una nuova proprietà che identifica il valore della chiave esterna (esattamente come lo definiremmo nel database) e decoriamo la navigation property Author con l’attributo <ForeignKey> specificando il nome della properietà/campo chiave di riferimento. Il database risultante sarà il seguente:

 

image

 

In questo modo possiamo sfruttare tutte le facilitazioni che già conosciamo in EF 4 e cioè usare il campo chiave anzichè la navigation property nelle operazioni di Add ed Update:

 

Dim _book As New Book With {
                     .Title = "Visual Basic 2010 Unleashed",
                     .AuthorId = 1                           
}

posted @ mercoledì 2 maggio 2012 8.00 | Feedback (1) | Filed Under [ Entity Framework Entity Framework Code First ]

domenica 22 aprile 2012

Entity Framework Code First: LocalDB

Come molti sapranno, il rilascio di SQL Server 2012 ha portato con sè una novità per gli sviluppatori, cioè SQL Server Express LocalDB. Si tratta di una versione molto light di SQL Server Express, che pur mantenendo tutte le caratteristiche dell’engine non richiede l’installazione completa della versione Express, e viene gestita automaticamente attivando il servizio SQL solo quando serve. Naturalmente questa caratteristica è disponibile solo in fase di sviluppo mentre per la distribuzione dell’applicazione è sempre necessario avere la versione Express o superiore.

Entity Framework, supporta questo tipo di database utilizzando la modalità Code First. L’operazione (semplice) da fare è specificare la stringa di connessione nel file .config come segue:

 

<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="Data Source=(LocalDB)\v11.0; Integrated Security=True; MultipleActiveResultSets=True" />
      </parameters>
    </defaultConnectionFactory>
</entityFramework>

 

La stringa di connessione richiede solo il Data Source che equivale al valore (LocalDB)\v11.0. Per il resto funziona tutto come già sappiamo.
Per supportare questo nuovo tipo di database engine, in Visual Studio 11 Beta è stata introdotta una nuova dialog chiamata SQL Server Object Explorer che è del tutto simile a all’attuale Server Explorer:

 

image


Quest’ultima, però, offre una serie di funzionalità aggiuntive che migliorano notevolmente la gestione sia della struttura che dei dati delle tabelle. Ad esempio, la maschera di visualizzazione dati prevede la possibilità di filtrare il numero dei record e di generare automaticamente lo script di insert dei record visualizzati:

 

image

 

image

 

Anche la maschera di mofica/creazione dello schema di una tabella offre funzionalità aggiuntive come la generazione “live” dello script TSQL e relativo salvataggio su file:

 

image

 

In definitiva grazie a questi nuovi strumenti è possibile sviluppare applicazioni per SQL Server con Entity Framework senza dover installare la versione Express. Ma se proprio abbiamo necessità di usare una versione di SQL completa, il SQL Server Object Explorer supporta tutte le versioni oltre a LocalDB Smile

posted @ lunedì 23 aprile 2012 8.00 | Feedback (1) | Filed Under [ Visual Studio Entity Framework Entity Framework Code First ]

martedì 10 aprile 2012

EF Code First Migrations: aggiornamenti automatici

Nell’articolo Entity Framework Code First Migrations viene illustrato il funzionamento di Code First Migrations, una funzionalità introdotta per mantenere allineato il database al modello dati. In particolare nell’articolo viene spiegato il metodo chiamato Code-Based Migrations perchè basato sulla generazione di codice per l’applicazione delle modifiche al database.
Esiste però anche una seconda modalità più semplice, chiamata Automated Migrations, che permette di ottenere lo stesso risultato ma in maniera trasparente e soprattutto automatica.

Consideriamo il modello utilizzato nell’articolo citato:

 

Public Class Book
     Property BookId As Integer
     Property Title As String     
     Property Author As Author
     <Column(TypeName:="char"), StringLength(10)> Property ISBN As String
     Property Price As Decimal     Property AddedOn As DateTime?
End Class
 
Public Class Author
     Property AuthorId As Integer
     Property FirstName As String
     Property LastName As String 
     Property Email As String
End Class
 
Public Class LibraryContext
     Inherits DbContext
     Property Books As DbSet(Of Book)
     Property Authors As DbSet(Of Author)
End Class

 

Eseguendo il codice, viene creato un nuovo database comprensivo della tabella __MigrationHistory:

 

image


Successivamente attiviamo Code Migrations eseguendo il comando enable-migrations nella console di NuGet:


 

image


così da generare automaticamente sia la classe Configuration che quella di inizializzazione del database per la creazione dello schema basato sul modello dati:

 

image

 

Per attivare gli aggiornamenti automatici bisogna modificare la classe Configuration impostando la proprietà AutomaticMigrationsEnabled a True:

 

Friend NotInheritable Class Configuration
         Inherits DbMigrationsConfiguration(Of LibraryContext)
 
         Public Sub New()
             AutomaticMigrationsEnabled = True
         End Sub
 
         Protected Overrides Sub Seed(context As LibraryContext)
         End Sub
End Class

 


Questo da solo però non basta perchè non generando manualmente il codice di aggiornamento attraverso i comandi Add-Migrations e Update-Database bisogna specificare una delle strategie di inizializzazione del database da applicare perchè sia il modello che il database siano allineati.
Per supportare tutto questo, il team di Entity Framework ha introdotto nella versione 4.3 una nuova classe chiamata MigrateDatabaseToLatestVersion() (che implementa sempre l’interfaccia IDatabaseInitializer(TContext)) che serve proprio allo scopo, cioè allineare il database con il modello.
Dunque applichiamolo allo startup dell’applicazione:

 

Database.SetInitializer(New MigrateDatabaseToLatestVersion(Of LibraryContext, Configuration))

 

A differenza delle altre strategie già esistenti, questa si basa oltre che sulla classe Context anche sulla classe Configuration che contiene tutte le impostazioni per applicare le modifiche al database, che poi sono le stesse usate con il metodo “manuale”.

Per verificare che tutto funzioni aggiungiamo una proprietà alla classe Book, ad esempio PublishedOn di tipo DateTime?, ed eseguiamo l’applicazione. Correttamente viene aggiunta la nuova proprietà al nostro database:

 

image

 

In realtà questo è lo scenario più semplice che, ovviamente, non si verifica quasi mai, perchè le modifiche al modello generalmente non si limitano all’aggiunta di un campo (almeno nelle prime fasi di sviluppo) ma possono essere anche più complesse. Infatti se solo proviamo a rimuove l’ultima proprietà aggiunta, l’applicazione non funziona più restituendo la seguente eccezione:

 

image

 

In pratica trattandosi di un’operazione con perdita di dati Entity Framework non esegue l’aggiornamento avvisando correttamente l’utente. Fortunatamente è possibile risolvere questo inconveniente specificandolo nella solita classe Configuration:

 

Friend NotInheritable Class Configuration
     Inherits DbMigrationsConfiguration(Of LibraryContext)
 
     Public Sub New()
          AutomaticMigrationsEnabled = True
          AutomaticMigrationDataLossAllowed = True
     End Sub
 
     Protected Overrides Sub Seed(context As LibraryContext)
     End Sub
End Class

 

La proprietà AutomaticMigrationsDataLossAllowed permette l’applicazione delle modifiche anche se queste comportano la perdita dei dati ma salvaguardando quelli esistenti. A questo punto possiamo modificare tranquillamente il nostro modello dati sicuri che ad ogni esecuzione EF lo aggiornerà automaticamente. Nel nostro esempio verrà rimosso il campo PublishedOn lasciando inalterati I dati esistenti.

Conclusioni
A differenza della metodologia Code-Based, quest’ultima è sicuramente più semplice perchè non dobbiamo alineare “manualmente” il database. Ovviamente il meccanismo di versioning non cambia, nel senso che tutte le modifiche sono salvate sempre nella tabella __MigrationHistory ed è possibile anche fare il rollback ad una versione specifica attraverso la console con il comando Update-Database –TargetMigration: [Nome_della_versione].

posted @ mercoledì 11 aprile 2012 8.00 | Feedback (0) | Filed Under [ Entity Framework Entity Framework Code First ]

EF 4.3: Connection settings

In un post precedente ho spiegato brevemente le varie opzioni possibili che si possono utilizzare per configurare la stringa di connessione al database nel file .config. Con la versione 4.3 è stato introdotta una nuova sezione per impostare le nuove opzioni di configurazione introdotte, chiamata <entityFramework>.

Questa sezione viene definita automaticamente nel file .config quando si ggiunge una referenza a Entity Framework 4.3 con NuGet:

<configSections>
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
            <section name="entityFramework"
                       type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections> 

Di default la sezione <entityFramework> è la seguente:

<entityFramework>
   <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
       <parameters>  
           <parameter value="Data Source=.\SQLEXPRESS; Integrated Security=True; MultipleActiveResultSets=True" />
       </parameters>
   </defaultConnectionFactory>
</entityFramework>

 

L’elemento <defaultConnectionString> serve per definire un oggetto IDbConnectionFactory da usare per creare una connessione ad un database definito dalla classe DbContext usata nell’applicazione. Se il tipo specificato prevede dei costruttori con parameteri è possibile specificarne il valore specificando l’elemento <parameter>.

Nella configurazione riportata precedentemente, viene specificato un database factory di tipo SqlConnectionFactory (per istanze SQL Server)  la cui stringa di connessione è specificata nell’elemento <parameter>. Da notare che la stringa di connessione non specifica l’attributo Initial Catalog perchè viene generato automaticamente a runtime. Questo comportamento è voluto proprio perchè lo scopo di una ConnectionFactory è quello di creare una connessione ad database noto, tanto è vero che funziona solo se non è specificata una stringa di connessione nella sezione <connectionStrings>.

Questa è la configurazione predefinita usata da Entity Framework pertanto è possibile anche ometterla.

Oltre alla stringa di connessione, in <entityFramework> si può specificare anche la strategia di inizializzazione del database.
Ad esempio, se volessimo utilizzare una strategia di tipo DropCreateDatabaseIfModelChanges() per l’esempio usato nell’articolo “Entity Framework code First” bisogna aggiuntere l’elemento <contexts>:

<entityFramework>
    <contexts>
       <context type="EF4Samples.LibraryContext, EF4Samples">
         <databaseInitializer type="System.Data.Entity.DropCreateDatabaseIfModelChanges'1[[EF4Samples.LibraryContext, EF4Samples]], EntityFramework" />
       </context>
    </contexts>
</entityFramework>

 

che equivale al codice:

Database.SetInitializer(New DropCreateDatabaseIfModelChanges(Of LibraryContext))

 

Grazie a questo approccio possiamo modificare il comportamento di Entity Framework senza modicare il codice, rendendo il tutto molto più flessibile.

posted @ martedì 10 aprile 2012 8.00 | Feedback (1) | Filed Under [ Entity Framework Entity Framework Code First ]

giovedì 29 marzo 2012

Creare un repository NuGet personalizzato

NuGet permette di distribuire librerie attraverso un repository centralizzato e chiunque può contribuire inviando i propri packages grazie ad un identificativo univoco che è possibile ottenere dal sito ufficiale. In area articoli trovate un ottimo articolo di Alessandro (Utilizzare e distribuire librerie gratuite in Visual Studio 2010 con NuGet) che spiega molto bene come creare un package e pubblicarlo su NuGet.org.
In questo post, però, vorrei evidenziare l’interessante possibilità di creare un repository personale da usare, ad esempio, per condividere e distribuire le librerie che generalmente si realizzano a supporto dello sviluppo di propri progetti soprattutto quando si lavora in un team (che è la situazione in cui mi sono trovato io).

Le possibilità che abbiamo sono due:

1) creare un repository locale

2) creare un repository remoto con IIS

Creare un repository locale
La cosa più semplice consiste nel creare una share di rete in cui copiarci i vari packages (file .nupkg) e poi aggiungerla tra i repository che NuGet usa come feed per la ricerca ed il download.
Semplicemente, nei settings di NuGet (raggiungibile dal menu Library Package Manager / Package Manager Settings), nella sezione Package Sources bisogna aggiungere il path della share di rete:

 


image

 

Da questo momento avremo a disposizione un altro repository da cui scaricare i package nella finestra di dialogo Manage NuGet Packages:

 

image

 

Ogni volta che aggiungiamo un package nella cartella condivisa, automaticamente sarà disponibile attraverso NuGet.

 

Creare un repository remoto
Se invece volessimo creare un repository remoto come NuGet.org, bisogna fare qualcosa in più, ovvero creare una piccola applicazione web per gestire sia il download che l’upload dei package.
La procedura è davvero semplice. Bisogna creare un nuovo progetto ASP.NET Empty Web Application (perchè non serve nulla!) ed aggiungere il package NuGet.Server digitando il seguente comando dalla consolle di NuGet che penserà a fare tutto:

PM> Install-Package NuGet.Server


 

Oltre ad aggiungere un po’ di librerie necessarie per far funzionare il sistema, viene configurata l’applicazione aggiungendo un po’ di settings nel file web.config. e in particolare vengono aggiunte due chiavi in <appSettings>:

 

<appSettings>              
    <!--   Set the value here to allow people to push/delete packages from the server.                                                        
            NOTE: This is a shared key (password) for all users.         -->

    <add key="apiKey" value="" />      
    <!--   Change the path to the packages folder. Default is ~/Packages.                                             
            This can be a virtual or physical path.         --> 
    <add key="packagesPath" value="" />
</appSettings>


packagePath
è la cartella contenente i package mentre apiKey è la chiave (scelta da noi) per consentire l’upload dei package.
Lasciando le impostazioni di default l’applicazione è già funzionante e se proviamo ad eseguirla avremo questo risultato:

 

image

 

che spiega come scaricare e pubblicare package. In particolare la prima url  (http://localhost:2485/nuget) è quella da specificare nei Package Sources come visto in precedenza. Come per la cartella condivisa, aggiungendo I packages nella cartella /Packages del Web Site, automaticamente saranno disponibili a tutti per il download.

In questo modo possiamo centralizzare il repository delle nostre librerie sfruttando tutte le funzionalità di NuGet come il versioning, l’update, ecc… Smile

posted @ giovedì 29 marzo 2012 0.07 | Feedback (1) | Filed Under [ Visual Studio Tools/Utilities NuGet ]

Powered by:
Powered By Subtext Powered By ASP.NET