Domanda

Questo sembra che dovrebbe essere abbastanza ovvio, ma qualcosa su Entity Framework me è confusa e non riesco a farlo funzionare.

Molto semplicemente, ho tre tabelle in cui i valori ID sono colonne di identità: Utenti (userId, nome utente) Categorie (categoryId, categoryName) JoinTable (UserId, CategoryId) composito.

Nella finestra di progettazione entità (questo è .net 4.0), quando ho importare queste tabelle, come previsto nella tabella join non appaiono ma gli utenti e categorie che 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);

ottengo lo stesso errore e nulla salvato il 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 join:

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

Sono chiaramente non riuscendo a capire come molti a molti rapporti sono inseriti. Che cosa mi manca?

È stato utile?

Soluzione

Si ha bisogno di chiamare SaveChanges () dopo l'aggiunta di entità utente e di categoria per il database, e quindi impostare la vostra associazione tra di loro.

Tuttavia, il vero problema qui è la seconda eccezione avete elencato. Se si guarda SQLProfiler o il profiler ADO.NET all'interno del debugger, si vedrà che durante il secondo SaveChanges chiamano 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 il vostro JoinTable correttamente (composito PK su entrambe le colonne).

Se guardo il negozio EntityModel tramite modello Browser, si vede che la colonna CategoryId all'interno JoinTable ha davvero StoreGeneratedPattern impostata su Identità mentre UserId è impostata su Nessuno. Perchè EF ha fatto questo durante la fase di generazione, quando un PK composito era presente è oltre me. Sarò distacco un bug su questo a MS, ma nel frattempo è possibile modificare manualmente il file edmx / SSDL dopo generazione per rimuovere l'identificatore di identità. Trova lo StoreGeneratedPattern = stringa "Identità" sotto il tag di proprietà del tag EntityType per il vostro JoinTable e rimuoverlo:

Modifica:

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

A:

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

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

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

Altri suggerimenti

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

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

In alternativa si può provare a 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 il metodo AttachTo (si consiglia di verificare se è già collegato). Quindi è possibile aggiungere la categoria di vostra entità utente utilizzando il metodo Add. Qualcosa di simile a questo:

myUser.Categories.Add(myCategory);

SaveChanges chiamata (). Che ha funzionato per me.

Quando nuovo genitore aggiunto al contesto, lo stato di tutti gli oggetti a modifiche oggetto albero a Aggiunto e quindi EF cerca di salvare tutti gli oggetti come nuovo record.

Fare riferimento questo link: http://nileshhirapra.blogspot.in/2012/03 /entity-framework-insert-operation-with.html

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top