Supponiamo di avere un data model basato su LINQ to SQL e avere la necessità, per qualche motivo, di operare sul campo che ne rappresenta la Primary Key.
Un modo utile per ottenere questo campo è quello di ricorrere alla Reflection in modo da recuperarne la PropertyInfo.
Conoscendo alcune caratteristiche della entity che stiamo esaminando, e controllando se la classe in oggetto è decorata con un attributo di tipo System.Data.Linq.Mapping.ColumnAttribute possiamo facilmente riuscire nel nostro scopo.
Creiamo quindi una classe statica per contenere i metodi che implementeremo come extension method della classe System.Type:
... using System.Collections.Generic; using System.Reflection; using System.Data.Linq.Mapping; ... namespace MyNamespace { public static class ExtensionMethods { // my extension methods goes here } }
In questa classe andremo a definire i metodi che ci servono per lo scopo. Come detto si tratta di extension methods, che in pratica rappresentano delle estensioni a delle classi già esistenti.
Il primo extension methods che implementeremo sarà appunto quello per verificare se esiste e quale sia la property che identifica la primary key:
public static PropertyInfo GetPrimaryKey(this Type TEntity) { PropertyInfo piReturn = null; // verifico che il tipo sia un generico e prendo sempre il tipo del primo argomento Type TTEntity = (TEntity.IsGenericType) ? TTEntity = TEntity.GetGenericArguments()[0] : null; if (TTEntity != null) { foreach (PropertyInfo pi in TTEntity.GetProperties()) { // cerco tra le varie proprietà della entity, quella che è decorata // con ColumnAttribute e questi a sua volta indica che il campo rappresenta // una primary key if (pi.GetCustomAttributes(false) .Where(att => (att is ColumnAttribute)) .Where(att => ((ColumnAttribute)att).IsPrimaryKey) .Count() == 1 ) { // trovata la primary key piReturn = pi; break; } } } return piReturn; }
Un altro metodo utile, potrebbe essere quello per capire se una primary key è anche una identity. Per questo scopo, implementiamo il secondo extension method, che stavolta estende direttamente una PropertyInfo:
public static bool IsIdentity(this PropertyInfo pi) { bool bIsIdentity = (pi.GetCustomAttributes(false) .Where(att => (att is ColumnAttribute)) .Where(att => ((ColumnAttribute)att).DbType .ToString().ToUpper().Contains("IDENTITY")) .Count() == 1); return bIsIdentity; }
Per la nostra demo, utilizzeremo un database molto semplice in cui sono presenti solo tre tabelle, da cui otteniamo il seguente data model:

A questo punto, utilizzando sempre per la demo una console application, possiamo scrivere:
static void Main(string[] args) { MyDataContext ctx = new MyDataContext(); PropertyInfo pi1 = ctx.TableWithoutPrimaryKeys.GetType().GetPrimaryKey(); PropertyInfo pi2 = ctx.TableWithPrimaryKeys.GetType().GetPrimaryKey(); PropertyInfo pi3 = ctx.TableWithPrimaryKeyIdentities.GetType().GetPrimaryKey(); string sFormat = "Entity={0}, PrimaryKey={1}, Identity={2}"; string s1 = string.Format(sFormat, "TableWithoutPrimaryKeys", ((pi1 != null) ? pi1.Name : "no primary key"), ((pi1 != null) ? pi1.IsIdentity().ToString() : "no identity")); string s2 = string.Format(sFormat, "TableWithPrimaryKeys", ((pi2 != null) ? pi2.Name : "no primary key"), ((pi2 != null) ? pi2.IsIdentity().ToString() : "no identity")); string s3 = string.Format(sFormat, "TableWithPrimaryKeyIdentities", ((pi3 != null) ? pi3.Name : "no primary key"), ((pi3 != null) ? pi3.IsIdentity().ToString() : "no identity")); Console.WriteLine(s1); Console.WriteLine(s2); Console.WriteLine(s3); Console.ReadLine(); }
Il nostro output sarà il seguente:

Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Change tracking e composition in Entity Framework
Utilizzare il metodo Index di LINQ per scorrere una lista sapendo anche l'indice dell'elemento
Utilizzare il metodo IntersectBy per eseguire l'intersection di due liste
Utilizzare il metodo CountBy di LINQ per semplificare raggruppamenti e i conteggi
Utilizzare il metodo ExceptBy per eseguire operazione di sottrazione tra liste