Usare il metodo Find di Entity Framework con le chiavi composte

Il metodo Find di Entity Framework 4.3 consente di recuperare un entità dal contesto in base alla chiave primaria.

Se l’entità è già presente nel contesto viene immediatamente restituita senza nessun round-trip al server in caso contrario viene effettuata una query di SELECT sul database.

L’oggetto recuperato viene collegato al contesto. Se l’oggetto non è presente nel contesto o nel database il metodo Find restituisce null.

Ad esempio:

_dbContext.Products.Find(1);

restituisce il prodotto con chiave 1 (int)

Supponiamo adesso di avere un prodotto con chiave primaria composta (composite key):

public class Product
    {
        public string StyleCode { get; set; }
        public string MaterialCode { get; set; }
        public string ColorCode { get; set; }
    }

Il mapping sarà di questo tipo:

public ProductMap()
        {
            HasKey(product => new { product.StyleCode,
                                       product.MaterialCode,
                                       product.ColorCode });
        }

Inseriamo nel db un prodotto in questo modo:

_dbContext.Products.AddOrUpdate(p => 
new { p.MaterialCode, p.StyleCode, p.ColorCode },
                                     new Product
                                         {
                                             StyleCode = "1",
                                             MaterialCode = "2",
                                             ColorCode = "3"
                                         });

 

ed invochiamo il metodo Find in questo modo:

_dbContext.Products.Find(1, 2, 3);

Molto probabilmente il risultato sarà null.

Questo perchè la firma del metodo Find è Find(params object[] keyValues) e quindi Entity Framework a questo punto non è ancora in grado di mappare i valori della chiave nell’ordine corretto.

Il mapping della classe Product va quindi modificato utilizzando il metodo HasColumnOrder:

public ProductMap()
        {
            HasKey(product => new { product.StyleCode, 
                                       product.MaterialCode,
                                       product.ColorCode });
            Property(p => p.StyleCode).HasColumnOrder(0);
            Property(p => p.MaterialCode).HasColumnOrder(1);
            Property(p => p.ColorCode).HasColumnOrder(2);
        }

In questo modo i parametri della chiave primaria vengono mappati in ordine.

Share

ORM – Non mi serve – non lo voglio – fa schifo!

E’ dal 2007 che seguo con attenzione il tema degli ORM (Object-Relational mapping) ed in questi anni mi sono imbattuto in diverse categorie di utilizzatori.

Se stai facendo o hai fatto (o sicuramente farai) una di queste affermazioni:

  1. Non sò che cos’è on ORM
  2. Sò cos’è ma non mi interessa usarlo
  3. Sono più bravo io a scrivere le query sul DB
  4. Se uso un ORM le performance sono un disastro
  5. L’ORM me lo sono fatto/me lo farò io in casa
  6. Si ho usato un po’ gli ORM ma ho capito che fanno schifo

 

ti invito a continuare a leggere.

  1. Non sò che cos’è on ORMRimando direttamente a wikipedia sul tema Object Relational Mapping
  2. Sò cos’è ma non mi interessa usarlo Non ti interessa utilizzare una soluzione che ti faccia scrivere meno codice, che esegua per te tutte le query CRUD al database, che magari faccia caching, che faccia lazy loading, che ti aiuti a disaccopiare gli oggetti di dominio dal database ecc. ecc.?
  3. Sono più bravo io a scrivere le query sul DBCertamente! Peccato che ormail le query generate da un buon ORM siano esattamente se non meglio di quelle che per anni ha scritto un buon sviluppatore. Personalmente non ho la presunzione che le mie query siano migliori del lavoro svolto dalla comunità di NHibernate ad esempio.
    Però è sicuramente vero che sei più bravo tu se l’ORM non lo sai usare…
  4. Se uso un ORM le performance sono un disastro Vero se non sai minimamente la teoria che ci stà dietro e se non conosci come è stata implementata nell’ORM che stai utilizzando. E comunque non vanno mai usati alla cieca ma almeno almeno con un SQL profiler o se sei un po’ più evoluto con i profiler NHibernate Profiler (nhprof.com), Linq to SQL Profiler(l2sprof.com) o Entity Framework Profiler.
    Ti sei accorto che la tua ignoranza sul funzionamento fa si che le query che fai al db siano di tipo n+1?
  5. L’ORM me lo sono fatto/me lo farò io in casa Mi permetto di ricordarti che siamo pagati per generare valore per i clienti e sicuramente dopo qualche mese di sviluppo avrai fatto magari anche un buon ORM ma non avrai generato nessun valore per il cliente finale.
  6. Si ho usato un po’ gli ORM ma ho capito che fanno schifo Questa è la categoria di dev che mi irrita maggiormente. E purtroppo questa è l’obiezione che sento più spesso.
    Di solito chi fa questa affermazione pretende di utilizzare un ORM senza leggerne un minimo di documentazione ma soprattutto senza essere a conoscenza di un minimo di teoria che sta dietro a questi “robi”.

Per appronfodire il tema sabato 9 ottobre si terrà a Bologna l’NHibernate Day che a dispetto del nome ritengo sarà un’interessante confronto in generale sugli ORM e non solo sul principale player qual è appunto NHibernate. Le liste sono piene ma ci si può mettere in waitlist.

Giusto alcuni speaker:

In primis ci sarà Ayende in persona cioè l’anima di NHibernate e di tool quali appunto NHProfiler.

E poi Andrea Saltarello che ormai parla di ORM con una profondissima conoscenza teorica (accademica oserei dire) e pratica.

E dulcis in fundo DotDotNet con Igor Antonacci, Luca Milan e Alberto Dallagiacoma: e da questi 3 c’è da aspettarsi tanta esperienza concreta sul campo.

Chissà se incontrerò qualche appartenente ai 6 gruppi individuati sopra…

Share

Listview, Entity framework e navigation property

Stavo creando una semplice ListView utilizzando Entity Framework sulla tabella Clienti.

Premetto che la tabella Clienti è in relazione con la tabella Agenti e quindi EF crea correttamente la Navigation Property tra l'entity clienti e l'entity agenti.

Creo la ListView, aggiungo il LinqDataSource e faccio il binding tra listview e datasource.

Fin qui tutto ok, anche il designer funziona correttamente e mi mostra tutte le colonne.

A runtime ricevo invece l'errore:

DataBinding: '[Agenti' is not a valid indexed expression.



Description: An
unhandled exception occurred during the execution of the current web
request. Please review the stack trace for more information about the
error and where it originated in the code.

Exception Details: System.ArgumentException: DataBinding: '[Agenti' is not a valid indexed expression.

Source Error:

Line 230: </td>
Line 231: <td>
Line 232: <asp:Label ID="Agenti_IDAgenteLabel" runat="server"
Line 233: Text='<%# Eval("[Agenti.IDAgente]") %>' />
Line 234: </td>

Tramite la navigation il designer ha generato una colonna per mostrarmi l'ID dell'agente collegato al cliente.

Il problema è nelle parentesi quadre che sono state aggiunte all'interno del metodo Eval.

Modificato il tag rimuovendo le parentesi quadrate

Text='<%# Eval("Agenti.IDAgente") %>' />

tutto funziona correttamente

Share