Trovare la Primary key di una entity mappata con LINQ to SQL

di Roberto Albano, in LINQ,

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

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi