5

Sembra che dovrebbe essere abbastanza ovvio, ma qualcosa riguardo al framework delle entità mi confonde e non riesco a farlo funzionare.Come si inseriscono o si aggiornano molte tabelle in .net Entità

Molto semplicemente, ho tre tabelle in cui i valori ID sono colonne di identità: utenti (userid, username) Categorie (IDCategoria, categoryName) JoinTable (UserId, CategoryId) composito.

Nella finestra di progettazione delle entità (questo è .net 4.0), quando si importano queste tabelle, come previsto, la tabella di join non viene visualizzata, ma Utenti e Categorie mostrano una relazione. Il seguente codice:

var _context = new MyContext(); 
var myUser = new User(); 
myUser.UserName = "joe"; 

var myCategory = new Category(); 
myCategory.CategoryName = "friends"; 

_context.Users.AddObject(myUser); 
myUser.Categories.Add(myCategory); 

var saved = _context.SaveChanges(); 

restituisce un errore di (anche se nulla è stato aggiunto al database):

An item with the same key has already been added. 

Se aggiungo quanto segue prima di salvare:

_context.Categories.AddObject(myCategory); 
myCategory.Users.Add(myUser); 

ho la stesso errore e nulla salvato nel db. Se risparmio il myUser e l'oggetto MyCategory prima di cercare di associarli, entrambi salvano, ma il secondo salvataggio getta un errore, senza nulla aggiungere alla tabella di unirsi:

Cannot insert the value NULL into column 'UserId', table '...dbo.JoinTable'; column does not allow nulls. INSERT fails. The statement has been terminated. 

sto chiaramente non riuscendo a capire quanti a molte relazioni sono inserite. Cosa mi manca?

+0

Qual è il tipo di proprietà ID? –

+0

int, identità –

+0

Ancora cercando di capirlo. Aggiungendo un terzo campo spurio alla tabella di join (DateCreated), posso forzare il progettista di entità a visualizzare la tabella di join. Posso quindi definire le relazioni: var myJoin = new JoinTable {UserId = myUser.UserId, CategoryId = myCategory.CategoryId}; E, quindi, il seguente verrà inserito correttamente quando salvato: _context.Categories.AddObject (myCategory); myCategory.JoinTables.Add (myJoin); myJoin.User = myUser; –

risposta

5

È necessario chiamare SaveChanges() dopo aver aggiunto le entità Utente e Categoria al database e quindi impostare l'associazione tra di esse.

Tuttavia, il vero problema qui è la seconda eccezione che hai elencato. Se si guarda SQLProfiler o il profiler ADO.NET all'interno del debugger, si vedrà che durante il secondo SaveChanges chiami simile a questa:

insert [dbo].[JoinTable]([UserId]) values (@0) select [CategoryId] from 
[dbo].[JoinTable] where @@ROWCOUNT > 0 and [UserId] = @0 and [CategoryId] = scope_identity() 

Ovviamente questo non funziona se è stato programmato correttamente il JoinTable (PK composito su entrambe le colonne).

Se guardo lo store EntityModel tramite Model Browser, mostra che la colonna CategoryId all'interno di JoinTable ha effettivamente StoreGeneratedPattern impostato su Identity mentre UserId è impostato su None. Perché EF l'ha fatto durante la fase di generazione quando era presente un PK composito è al di là di me. Inserirò un bug su questo in MS, tuttavia nel frattempo è possibile modificare manualmente il file edmx/ssdl dopo la generazione per rimuovere lo strumento Identity.Trova lo StoreGeneratedPattern = stringa "Identità" sotto il tag di proprietà del tag EntityType per il vostro JoinTable e rimuoverlo:

Cambio:

<Property Name="CategoryId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> 

A:

<Property Name="CategoryId" Type="int" Nullable="false" /> 

Poi, quando si esegue la il codice si otterrà una migliore query di inserimento (e non più un'eccezione!):

insert [dbo].[JoinTable]([UserId], [CategoryId]) values (@0, @1) 
1

Il modo in cui ho fatto questo è di generare prima un'entità di categoria valida con la chiave di entità.

Category myCategory = _context.Categories.First(i => i.CategoryID == categoryIDToUse); 

Oppure si può cercare di creare l'entità come uno stub per salvare il colpo al DB:

Category myCategory = new Category{CategoryID = categoryIDToUse }; 

Quindi aggiungere a tale soggetto di set di entità (CategorySet) sul ObjectContext utilizzando l'AttachTo metodo (si consiglia di verificare se è già collegato). Quindi puoi aggiungere la Categoria all'entità Utente utilizzando il metodo Aggiungi. Qualcosa di simile a questo:

myUser.Categories.Add(myCategory); 

SaveChanges di chiamata(). Questo ha funzionato per me.

+0

Forse questo è un cambiamento con 4.0, ma non c'è nessun oggetto "categoryset" sotto myUser, ma ci sono "categorie": myUser.Categories.Add (myCategory); Ma questo ho già nel mio esempio di codice sopra. Non sono proprio sicuro di cosa intendi per "generare una categoria valida con la chiave dell'entità"? –

+0

Sto usando EF v1.0. Ho aggiornato la mia risposta. Con "categoryset" intendevo qualunque fosse il nome di EntitySet per le entità di categoria. Vedo che è 'Categorie' e ho aggiornato il codice di esempio. Spero che aiuti. – DaveB

+0

Giusto, purtroppo questo è quello che ho fatto con i risultati mostrati sopra. Utilizzando: myCategory.Users.Add (myUser) AND/OR myUser.Categories.Add (myCategory) restituisce 'un elemento con la stessa chiave è già stato aggiunto' –

Problemi correlati