Durante la realizzazione del layer di accesso ai dati di una semplice demo app, per il quale avevo scelto di utilizzare LINQ to Sql, sono incorso in un noioso bug nel recupero dei valori delle PrimaryKey, nel caso in cui questi siano autogenerati dal server di database.
Supponiamo di avere una tabella del tipo seguente, in cui la PK sia di tipo uniqueidentifier, automaticamente inizializzata per le nuove righe tramite la funzione di sistema newid():
Creiamo un nuovo DataContext di LINQ to Sql e importiamo al tabella creata; il designer crea una nuova entity con i campi omonimo delle colonne sul database:
Spesso, lato schema DB, i nomi delle chiavi contengono un riferimento alla tabella a cui appartengono. Per quanto riguarda le entità di dominio, invece, preferisco che gli identificativi si chiamino tutti allo stesso modo, sia per una questione di uniformità e leggibilità (non essendoci FK ma semplici riferimenti, non ho più la necessità di avere nomi diversi), sia perchè, ad esempio, potrei pensare di far implementare a tutte le mie entity un'interfaccia IHasIdentifier che esponga la proprietà Id e utilizzarla per implementare un GetById generico. Quindi, forte delle mie convinzioni, procedo alla modifica sulla entità di L2S generata dal designer:
Inoltre, mi ricordo anche di impostare, sulla property grid, che la proprietà Id è auto generata da DB e che deve essere recuperata dopo una query di Insert:
In fase di fetch, LINQ to Sql svolge egregiamente il suo lavoro, trasformando correttamente ogni condizione sulla proprietà Id in una where sulla colonna MySampleId:
Ciò purtroppo non accade quando, dopo una query di Insert, L2S tenta di recuperare il valore della chiave generata da database. Come si nota dalla query, infatti, viene erroneamente cercata una colonna chiamata Id, con successivo ed ovvio errore di Sql Server.
Ho segnalato il problema nei forum di MSDN, e mi è stato risposto che si tratta di un bug che verrà corretto con il rilascio del SP1. Attualmente ci sono solo due soluzioni:
- Utilizzare i medesimi nomi per proprietà e colonne
- Inizializzare manualmente la proprietà ad un nuovo Id sul costruttore della entity
Un'ultima curiosità: tutto ciò non si verifica nel caso in cui la PK sia un Identity e il motivo è che, in quel caso, Linq to Sql utilizza SELECT SCOPE_IDENTITY per recuperare il nuovo valore.
Technorati Tags:
LINQ to Sql