lunedì 12 settembre 2011

Entity Framework molti-a-molti e le chiavi di mal definiti


Ecco una nuova voce per le "cose ​​stupide da parte mia che non erano evidenti a causa di oscuri messaggi di errore" libro. In realtà, il messaggio di errore fa certo senso a posteriori, ma ripeto, tutto è sempre molto più chiaro dopo il fatto.
Lo scenario in questo caso si riferisce ai seguenti tre tabelle ASafaWeb :
Database diagramma che mostra una tabella di mappatura
Quello che questi ragazzi stanno descrivendo è che quando una voce di registro di una scansione è stato creato, può avere molte voci di X-Powered-By header (questo passa attraverso una raccolta delimitato da virgole). Un modo tipico di normalizzare questa relazione è quello di eliminare una tabella di mappatura in mezzo, in questo caso il "LogXPoweredByHeader". La cardinalità visualizzata sopra è proprio quello che ci si aspetta in questo scenario.
Quando questo modello viene mantenuta attraverso in Entity Framework (versione 4.1 in questo caso), la tabella di mappatura viene abbandonata in quanto EF è in grado di modellare le voci di intestazione come una raccolta contro l'attributo XPoweredByHeaders.Ecco cosa si ottiene (alcune entità sono state escluse nell'immagine per ragioni di brevità):
Entity Framework modello generato dal database
Fin qui, tutto bene. Per ragioni di semplicità, ecco come una voce di registro nuovo si sta creando:
var log = nuovo log ();
 / / Imposta un mucchio di altri attributi sul log
 var = xPoweredByHeaders db.XPoweredByHeaders.First ();
log.XPoweredByHeaders.Add (xPoweredByHeaders);
db.Logs.AddObject (log);
db.SaveChanges ();
Come per il commento, tutta una serie di altri attributi sono salvati, ma voglio concentrarmi solo sulla attributo XPoweredByHeaders per ora. Sono anche solo andando a prendere il primo che posso trovare nella tabella XPoweredByHeader di mantenere questo molto semplice.
Ecco dove va tutto storto:
Un valore condiviso tra enti o associazioni viene generato in più di una località.  Controllare che la mappatura non dividere un EntityKey a più memorizzare colonne generate.
Per motivi di SEO, ecco la parte importante di che gli errori di nuovo:
Un valore condiviso tra enti o associazioni viene generato in più di una località. Controllare che la mappatura non dividere un EntityKey a più memorizzare colonne generate.
Eh?! Che valore sto condivisione tra enti o associazioni? E perché essendo generato più di una volta? E io non sono a conoscenza di divisione delle chiavi entità. Molto bizzarro.
Dopo una serie di usare Google senza successo e chiedendo / lamentarsi su Twitter, ho deciso di scavare più a fondo nella definizione della tabella. Ecco lo script di creazione:
CREATE TABLE [dbo] . [LogXPoweredByHeader] (
     [LogId] [int] IDENTITY ( 1 , 1 ) NOT NULL,
     [XPoweredByHeaderId] [int] NOT NULL,
 CONSTRAINT [PK_LogXPoweredByHeader] PRIMARY KEY 

  
Vedere il problema? E 'subito saltata fuori di me ed è sulla seconda riga della dichiarazione, la colonna "LogId" è stato specificato come una colonna di identità. Ah, c'è la lampadina momento: come è questa colonna di andare a tenere una chiave esterna se è una identità?!
Chiaramente questo non era consapevole decisione di progettazione ed è più un caso di di progettazione visiva in SSMS prendere alcune libertà a mio nome. Naturalmente si tratta di una soluzione semplice e anche se appena ho rettificato il DB e aggiornato il edmx ho fatto un rapido diff contro l'ultima revisione nel controllo del codice sorgente (il testo è cancellato.evidenziata ):
< Proprietà Nome = " LogId " Type = " int " Nullable = " falso " StoreGeneratedPattern = " Identità " />
 
Quindi l'attributo StoreGeneratedPattern è stata abbandonata e subito tutto quello che ha iniziato a comportarsi esattamente come avevo voluto in primo luogo. Col senno di poi, sì, era un valore che era stato generato in più di un luogo, ma si potrebbe pensare EF avrebbe potuto essere un po 'meglio a riportarlo. Voglio dire pensarci: se una tabella di mappatura (EF sa che è una tabella di mappatura), ha due colonne con ciascuno essere un FK a uno dei tavoli nella mappa ma in qualche modo uno di loro è anche una identità (che EF sa anche ), non avrebbe senso per spiegare questo nel messaggio di errore? Speriamo che la prossima persona che Googles questo otterrà una risposta più diretta a titolo di questo post.


Corso Visual Studio - Corsi Visual Studio
Corso .Net- Corso Dot.Net - Corso Vb.net
Corso C# - Corso PHP - Corso Joomla

Nessun commento:

Posta un commento