Per impostazione predefinita EF non applica nessun metodo per gestire situazioni di conflitti di concorrenza nel senso che esegue gli aggiornamenti basandosi esclusivamente sulla chiave primaria per la clausola WHERE dell’UPDATE e della DELETE.
Tuttavia è possibile modificare questo comportamento applicando un modello di concorrenza ottimistica impostando la proprietà ConcurrencyMode sul valore Fixed per tutti quei campi che si desidera vengano inclusi nella clausola WHERE.
Consideriamo a titolo di esempio la tabella Customers del database Northwind e supponiamo di voler applicare un controllo di concorrenza sul campo CompanyName:
Che nel modello di definizione dati sarebbe così:
1: <Property Type="String" Name="CompanyName"
2: Nullable="false"
3: MaxLength="40" FixedLength="false" Unicode="true"
4: ConcurrencyMode="Fixed" />
Ora, se proviamo a simulare una modifica del campo CompanyName *dopo* il caricamento dei dati e *prima* del salvataggio delle modifiche, alla chiamata del metodo SaveChanges() avremo una eccezione di tipo OptimisticConcurrencyException. E’ grazie a questa eccezione che siamo in grado, a questo punto, di gestire il conflitto:
1: Using db As New NorthwindEntities
2: Dim c = db.Customers.FirstOrDefault(Function(item) item.CustomerID = "ALFKI")
3: c.CompanyName = "Alfreds Futterkiste Inc."
4: c.PostalCode = "12208"
5:
6: Try
7: db.SaveChanges()
8: Catch ex As OptimisticConcurrencyException
9: Console.WriteLine("I dati sono stati modificati rispetto all'ultimo caricamento") 10: Console.WriteLine("1. Sovrascrivi") 11: Console.WriteLine("2. Annulla le mie modifiche") 12: Dim v As String = Console.ReadLine()
13: If v = "1" Then
14: db.Refresh(Objects.RefreshMode.ClientWins, c)
15: Else
16: db.Refresh(Objects.RefreshMode.StoreWins, c)
17: End If
18: db.SaveChanges()
19: End Try
20: End Using
Per stabilire che tipo di modifiche applicare si utilizza il metodo Refresh() dell’ObjetContext che accetta una enumerazione che indica quali valori confermare. In particolare:
- Objects.RefreshMode.ClientWins specifica che i dati da inviare al database sono quelli contenuti nell’entity, quindi sovrascrive le modifiche fatte sul database;
- Objects.RefreshMode.StoreWins significa che i dati da inviare al database sono quelli attuelmente nel database, quindi annulla le modifiche fatte all’entity
Scelta l’operazione da eseguire, si richiama nuovamente il metodo SaveChanges() per confermare le modifiche.
Nel nostro esempio, scegliendo l’opzione 1, dietro le quinte verrebbero generati, nell’rdine, i seguenti comandi SQL:
1) Una SELECT in corrispondenza della riga 2 per caricare il record con ID = “ALFKI”
2) un UPDATE in corrispondenza della riga 7 per l’aggiornamento che prevede anche il campo CompanyName nella clausola WHERE essendo ConcurrencyMode = Fixed:
3) una SELECT in corrispondenza della riga 14 per recuperare i valori aggiornati dal database da utilizzare nell’update successivo, in quanto si è deciso di sovrascrivere i dati con quelli presenti nell’entity “c”;
4) Un UPDATE in corrispondenza della riga 18 per confermare l’aggiornamento con i valori correnti:
Come si vede dal comando SQL, per il campo CompanyName nella WHERE, viene utilizzato l’ultimo valore recuperato con il comando SELECT del punto (3) perché l’UPDATE abbia successo.
Nel caso in cui avessimo scelto l’opzione 2 (StoreWins), non sarebbe eseguita l’UPDATE del punto (4) perché sarebbero valide le modifiche esistenti nel database e, al SaveChanges(), verrebbero aggiornati i dati dell’entity con gli ultimi dati del database annullando le modifiche fatte alle righe 3 e 4.
Entity Framework utilizza una stringa di connessione un po’ più complessa del normale perché oltre a specificare la connectionString del provider ADO.NET, occorre definire anche l’EntityClient provider ovvero la posizione dei file di mapping (.csdl, ssdl, msl). Di default EF include questi file come risorsa nell’assembly in cui sono definiti creando una connessione del tipo:
metadata=res://*/Northwind.csdl|res://*/Northwind.ssdl|res://*/Northwind.msl; ….
res:// indica che il file è una risorsa la cui posizione è specificata dal “persorso” che segue. Questo percorso rappresenta l’assembly e di default il designer specifica * (asterisco) che istruisce EF di cercare nell’assembly correntemente caricato, in quelli referenziati ed in tutti quelli presenti nella cartella \bin dell’applicazione.
Questo, sebbene semplifichi la stringa di connessione, aggiunge un certo overhead dovuto alla ricerca dei file di mapping nei vari assembly. Per evitarlo sarebbe opportuno specificare sempre il full name dell’assembly in cui sono definiti i file:
metadata=res://MyAssembly.dll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null/Northwind.csdl|…;
Questo accorgimento velocizza tutta la fase di caricamento dei file di mapping e vale sicuramente la modifica davvero piccola che bisogna fare manualmente :)
Dall'uscita della Release Candidate di Visual Studio e .Net 4.0 sono state rilasciate alcune patch per correggere alcuni problemi relativi a VS. L'elenco è questo:
Intellisense Crash Issue
Risolve crash improvvisi provocati dall'IntelliSense in alcune configurazioni di VS. Le patch da scaricare sono due:
1) Intellisense Crashes when using Tablet, Multi-touch, Screen Readers
2) Visual Studio 2010 crashes with System.InvalidOperationException when performing QuickInfo
Hotfix for “Issue with Auto-Generated Designer Files not Adding Controls” relativi al designer asp.net
Si tratta di un problema relativo al designer WebForms che non aggiunge correttamente i controlli nel file associato all'aspx (designer.vb o designer.cs).
Trovate maggiori dettagli qui, mentre il download qui.
Un riepilogo generale lo trovate sul blog di Scott:
Some VS 2010 RC Updates (including patches for Intellisense and Web Designer fixes)
Ho avuto modo di provare NDepend 3.x, un tool molto utile per uno sviluppatore .net perchè consente un’analisi approfondita del proprio codice .net in maniera grafica e testuale. Esistono davvero decine di report e grafici che permettono di avere svariate statistiche a partire da quelle “classiche” come il numero totale di Type, metodi, linee di codice, fino a quelle più interessanti come il numero di metodi utilizzati, i metodi con più linee di codice, i metodi non utilizzati, numero di chiamate, ecc.. passando da lcune informazioni curiose come la % di commenti sul totale del codice oppure il numero di istruzioni IL corrispondenti.
Alcune funzionalità molto interessanti sono:
- Dependency Cycles
- Compare Builds
- Manage Complexity and Dependencies
- Code Query Language (CQL) ovvero un linguaggio query di interrogazione del codice di un assembly che permette di fare svariatitipi di ricerca
- 82 Code Metrix
- Diagrams
Inoltre NDepend si integra perfettamente in Visual Studio 2010/2008 e 2005 permettendo l’analisi dei progetti correntemente aperti.

NDepend rappresenta sicuramente un utilissimo strumento di analisi dei propri progetti .net
A distanza di qualche giorno, il Team di Entity Framework ha pubblicato gli aggiornamenti degli addon EF per renderli compatibili con Visual Studio 2010 RC.
Eccoli:
- Feature CTP 3
- POCO Template, comprendente sia le versioni C# che VB che il supporto per progetti WebSite. Tutti i dettagli li potete trovare qui: Entity Framework POCO Template updated for Visual Studio 2010 Release Candidate.
Purtroppo questi template non saranno parte integrante di Visual Studio ma potranno essere scaricati dalla Visual Studio Gallery. Peccato.