27

Nov

[EF] Da DbContext a ObjectContext e ritorno… ricavare le chiavi di ogni entity

Hi Guys

 

sono sull’aereo per andare in Finlandia all’MCT Summit (seguiranno post dedicati)

quest’anno chi mi conosce sa che ho avuto varie disavventure importanti e quindi ho disertato un po’ blog e forum

ma siamo sempre in tempo per rimediare!

 

 

EntityFramework! questo sconosciuto… insomma, ormai esiste da mezza decade…

ma i bravi ragazzi di Microsoft, hanno deciso di venire incontro ad alcune richieste della community mondiale, ed hanno rifatto il modello ad oggetti, passando da quello basato sull’ObjectContext e ObjectSet, a quello su DbContext e DbSet

molto è cambiato, è sicuramente più agnostico, ma ha perso alcune funzionalità utili (come si dice dalle mie parti) assai!

ma non disperate, come sempre, Microsoft è la copia spudorata di un libro di fisica, e come la materia, nulla si crea/distrugge, tutto si trasforma

 

a questo punto dovreste pensare 2 cose:

  1. come si risale all’ObjectContext dal DbContext?
  2. a che mi serve?

 

per la domanda 1, la risposta è semplice:

DbContext context;

var ocontext = ((IObjectContextAdapter)context).ObjectContext;

 

mentre per la domanda 2, le risposte sono variopinte, alcune di religione, se è giusto o no, etc…, altre legate alla necessità

ad esempio potremmo usare il vecchio ObjectContext per fare delle query in Entity-SQL, che essendo una stringa dà alcune libertà, togliendo alcune sicurezze

ad esempio potremmo usare l’ObjectContext per ricavare un ObjectSet e da quello risalire ai metadati dell’Entità, molto utile, cosa che alternativamente si può fare solo andando a ravanare nelle risorse dell’assembly che ospita il nostro EDM, e da li prendere gli XML propri di EF, poi da parsare, etc………………

un esempio pratico?

ricavare le chiavi di una entità, qualunque essa sia

public static object[] KeyValues(this DbContext context, T arg)
    where T : class
{
    var set = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet();
    var entitySet = set.EntitySet;
    return entitySet.ElementType.KeyMembers.Select(k => arg.GetType().GetProperty(k.Name).GetValue(arg, null)).ToArray();
}

 

per comodità ho usato la sintassi di un ExtensionMethod, così da poterlo utilizzare praticamente ovunque, basta che il metodo sia in una classe astratta e che questa sia visibile con l’eventuale opportuno using dalla classe in cui stiamo scrivendo

 

un esempio d’uso è questo: immaginiamo uno scenario tipico in cui andiamo sul DB tramite EF, ed ovviamente la riga dopo abbiamo già fatto il Dispose del context chiudendo connessioni ed altro; detto anche scenario disconnesso

se voglio implementare un generico metodo (sempre extension, è più comodo) per gestire in modo centralizzato (per non dover sempre riscrivere la stessa cosa) il Modify (metodo che salva le modifiche ad una entità), questo è il codice che posso scrivere:

public static void Modify(this DbContext context, T arg)
   where T : class
{
    var original = SetOf(context).Find(KeyValues(context, arg)) as T;
    context.Entry(original).CurrentValues.SetValues(arg);
}

 

in pratica, mi riprendo l’oggetto originale, e gli applico le modifiche dell’oggetto che ho appena usato, questo è fattibile grazie al Find ed al nostro nuovo KeyValues

 

stesso discorso per un generico Remove:

public static void Remove(this DbContext context, T arg)
    where T : class
{
    var original = SetOf(context).Find(KeyValues(context, arg)) as T;
    SetOf(context).Remove(original);
}

 

 

un saluto a tutti

by Antonio Esposito on 11/27/2013
Post archive