Come posso ottenere l'ID dell'entità inserita nel framework Entity? [chiuso]


611

Ho un problema con Entity Framework in Asp.net. Voglio ottenere il valore ID ogni volta che aggiungo un oggetto al database. Come posso fare questo?


16
La risposta di Ladislav Mrnka di seguito è la risposta corretta e dovrebbe essere accettata come tale.
CShark,

3
L'OP ha pubblicato una sola volta con il suo account, questa domanda per essere più specifica. Ciò gli ha concesso quasi 2k di reputazione (!), La risposta non è contrassegnata come accettata perché l'account è stato abbandonato da quel giorno.
MurariAlex,

1
Se hai solo bisogno dell'ID per usarlo in una relazione di chiave esterna, puoi considerare invece di impostare la proprietà di navigazione della tua entità dipendente sull'entità precedentemente aggiunta. In questo modo non devi preoccuparti di chiamare SaveChangessubito solo per ottenere l'ID. Ulteriori letture qui .
B12,

Per Entity Framework Core 3.0, aggiungi il parametro acceptAllChangesOnSuccess come vero: await _context.SaveChangesAsync (true);
Mike

Risposte:


1006

È abbastanza facile Se si utilizza DB generato Ids (come IDENTITYin MS SQL) basta aggiungere entità ObjectSete SaveChangessulle relative ObjectContext. Idverrà riempito automaticamente per te:

using (var context = new MyContext())
{
  context.MyEntities.Add(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Yes it's here
}

Il framework delle entità per impostazione predefinita segue ciascuna INSERTdi esse SELECT SCOPE_IDENTITY()quando Idvengono utilizzati i messaggi automatici generati .


34
Quindi stai facendo una domanda sbagliata. Se hai un problema con l'eccezione, dovresti porre una domanda che mostra la tua eccezione (e l'eccezione interna) e lo snippet di codice che causa quell'errore.
Ladislav Mrnka,

3
. Assicurarsi che l'Ente si sta aggiungendo è un'entità valida ad esempio, qualsiasi cosa con una restrizione del database di "non nullo" deve essere compilato, ecc
fran

4
@LadislavMrnka: che dire delle proprietà di navigazione dell'oggetto appena creato? Non sembrano essere popolati automaticamente dopo aver salvato le modifiche.
Isaac Kleinman,

4
Consideriamo il seguente scenario: table1 dovrebbe generare un'identità @@ per usarla in table2. Sia tabella1 che tabella2 dovrebbero essere nella stessa transazione, ad esempio un'operazione SaveChange deve salvare entrambi i dati della tabella. L'identità @@ non verrà generata se non viene invocato un 'SaveChanges'. come possiamo affrontare questa situazione?
Arash,

7
@Djeroen: se usi l'ID generato dal database, devi prima inserire quegli oggetti nel database. Se è necessario disporre di ID prima dell'inserimento, è necessario creare la propria logica per ottenere ID univoci prima di inserire i dati e non utilizzare la colonna Identity nel database.
Ladislav Mrnka,

124

Stavo usando la risposta di Ladislav Mrnka per recuperare con successo gli Id quando usavo l'Entity Framework, ma sto postando qui perché non lo avevo usato (cioè usandolo dove non era richiesto) e pensavo che avrei pubblicato i miei risultati qui in le persone stanno cercando di "risolvere" il problema che ho avuto.

Si consideri un oggetto Ordine che ha una relazione di chiave esterna con il Cliente. Quando ho aggiunto un nuovo cliente e un nuovo ordine contemporaneamente, stavo facendo qualcosa del genere;

var customer = new Customer(); //no Id yet;
var order = new Order(); //requires Customer.Id to link it to customer;
context.Customers.Add(customer);
context.SaveChanges();//this generates the Id for customer
order.CustomerId = customer.Id;//finally I can set the Id

Tuttavia, nel mio caso, ciò non era necessario perché avevo una relazione di chiave esterna tra customer.Id e order.CustomerId

Tutto quello che dovevo fare era questo;

var customer = new Customer(); //no Id yet;
var order = new Order{Customer = customer}; 
context.SaveChanges();//adds customer.Id to customer and the correct CustomerId to order

Ora, quando salvo le modifiche, viene aggiunto all'ordine anche l'ID generato per il cliente. Non ho bisogno di ulteriori passaggi

Sono consapevole che questo non risponde alla domanda originale, ma ho pensato che potesse aiutare gli sviluppatori che non conoscono EF a utilizzare in modo eccessivo la risposta più votata per qualcosa che potrebbe non essere necessario.

Ciò significa anche che gli aggiornamenti vengono completati in un'unica transazione, evitando potenzialmente i dati orphin (tutti gli aggiornamenti sono completi o nessuno lo fa).


8
Grazie ! IMPORTANTE Suggerimento per le migliori pratiche: var order = new Order {Customer = customer}; Ciò mostra la potenza di Entity Framework di assegnare l'oggetto correlato e l'id verrà automaticamente aggiornato.
LA Guy 88

Grazie per queste informazioni aggiuntive alla risposta. È stato molto utile per salvare un roundtrip DB quando si utilizza EF.
Prasad Korhale,

Grazie mille per questo. Questo e 'esattamente quello che stavo cercando. Credevo solo che potesse esserci un modo migliore di chiamare "SaveChanges" due volte
Josh,

1
Si prega di menzionare anche nella risposta (preferibilmente in grassetto) che questo risolve un comportamento di transazione. Se uno degli oggetti non viene aggiunto, parte della transazione non avrà esito positivo. Ad esempio, l'aggiunta di persona e studente. La persona ha successo e lo studente fallisce. Ora la persona è ridondante. Grazie per questa ottima soluzione!
Imran Faruqi,

32

È necessario ricaricare l'entità dopo aver salvato le modifiche. Perché è stato modificato da un trigger di database che non può essere monitorato da EF. Quindi dobbiamo ricaricare nuovamente l'entità dal DB,

db.Entry(MyNewObject).GetDatabaseValues();

Poi

int id = myNewObject.Id;

Guarda la risposta di @jayantha nella seguente domanda:

Come posso ottenere l'ID dell'entità inserita nel framework Entity quando utilizzo defaultValue?

Anche la risposta di @christian nella seguente domanda può aiutare:

Entity Framework Aggiorna contesto?


2
Ciao, quando mi piace, ricevo l'errore di compilazione che dice: non è possibile risolvere le proprietà, ad esempio Id o Nome, mi potete aiutare per favore?
Morteza Azizi,

1
@MortezaAzizi Sembra essere un errore di proprietà non gestita o null proprietà ma puoi per favore spiegare o scrivere qualche frammento di codice?
QMaster,

3
Non dovresti farlo .GetDatabaseValues();se hai appena salvato il tuo modello nel DB. L'ID dovrebbe ripopolare automaticamente nel modello.
vapcguy,

3
@QMaster Ad eccezione del fatto che EF è anche in grado (e lo fa) di eseguire la stessa istruzione SQL e popola l'ID dell'oggetto. Altrimenti, come è possibile salvare più oggetti dipendenti contemporaneamente? Come sarebbe GetDatabaseValues()se non conoscesse l'ID dell'oggetto da cercare nel database?
Krillgar,

2
@vapcguy vedo. Grazie per i tuoi ascolti. Lo verificherò in entrambe le versioni di EF ASAP.
QMaster,

16

Si prega di fare riferimento a questo link.

http://www.ladislavmrnka.com/2011/03/the-bug-in-storegeneratedpattern-fixed-in-vs-2010-sp1/

Devi impostare la proprietà di StoreGeneratedPattern su identity e quindi provare il tuo codice.

Oppure puoi anche usare questo.

using (var context = new MyContext())
{
  context.MyEntities.AddObject(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Your Identity column ID
}

7
Come la risposta più votata.
Lewis86,

2
StoreGeneratedPatternera il pezzo mancante per me.
BurnsBA

1
Questa è la strada da percorrere quando si lavora con ORACLE e ON-Insert Trigger,
Karl

il collegamento è interrotto - dominio parcheggiato
t.durden

Salve con Oracle, ho dovuto impostare StoreGeneratedPattern in Entity: andare al visualizzatore di modelli, trovare la tabella e PK, selezionare la proprietà StoreGeneratedPattern e impostare su Identity. Funziona come indicato nella risposta sopra. Questo è per il caso in cui hai un trigger che popola il tuo PK da una sequenza sull'insert.
Rob,

15

L'oggetto che stai salvando dovrebbe avere una corretta Iddopo aver propagato le modifiche nel database.


27
hai visto l'eccezione interiore? ;-)
Snowbear

6

Puoi ottenere l'ID solo dopo il salvataggio, invece puoi creare un nuovo Guid e assegnarlo prima di salvare.


4

Mi imbatto in una situazione in cui ho bisogno di inserire i dati nel database e contemporaneamente richiedere l'id primario utilizzando il framework di entità. Soluzione:

long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
 {
    InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
    InfoBase.Add(generalinfo);
    InfoBase.Context.SaveChanges();
    id = entityclassobj.ID;
    return id;
 }

4

Tutte le risposte sono molto adatte ai propri scenari, ciò che ho fatto diversamente è che ho assegnato int PK direttamente dall'oggetto (TEntity) che Add () ha restituito a una variabile int come questa;

using (Entities entities = new Entities())
{
      int employeeId = entities.Employee.Add(new Employee
                        {
                            EmployeeName = employeeComplexModel.EmployeeName,
                            EmployeeCreatedDate = DateTime.Now,
                            EmployeeUpdatedDate = DateTime.Now,
                            EmployeeStatus = true
                        }).EmployeeId;

      //...use id for other work
}

quindi invece di creare un intero nuovo oggetto, prendi semplicemente quello che vuoi :)

MODIFICA Per Mr. @GertArnold:

inserisci qui la descrizione dell'immagine


3
Non è davvero utile aggiungere un metodo non divulgato per assegnare un ID. Questo non è nemmeno correlato a Entity Framework.
Gert Arnold,

1
@GertArnold .. ho avuto la stessa domanda dell'OP ho trovato le risposte e le ho trasformate in una singola riga, e non ho mai sentito parlare del termine metodo non divulgato per spiegare?
IteratioN7T

3
Ciò significa solo che non mostri (sveli) tutto ciò che fai. Forse non è semplicemente descritto chiaramente, non lo so. Quello che so è che Add(se questo è DbSet.Add) non non è magicamente assegnare un valore a EmployeeId.
Gert Arnold,

3
Non senza SaveChanges. Impossibile. A meno che tu non abbia qualche altro processo che assegni EmployeeId, ad esempio nel Employeecostruttore di. O sei nel core EF utilizzando ForSqlServerUseSequenceHiLo. Comunque, non stai dando l'intera immagine.
Gert Arnold,

3
La mia ultima osservazione sarà: questo non è un comportamento EF standard. Dovresti fornire maggiori dettagli sul tuo ambiente. Versione EF, marca e versione del database, classe Employee, dettagli della mappatura.
Gert Arnold,

3
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;

Questo funzionerà.


4
Il repository non è responsabile del salvataggio delle modifiche nel database. È un lavoro di UnitOfWork.
Tchelidze,

5
Inoltre, non è assolutamente chiaro cosa Repositorysia. E "questo funzionerà" è una spiegazione !.
Gert Arnold,

2

Esistono due strategie:

  1. Usa generato dal database ID( into GUID)

    Contro:

    Dovresti esibirti SaveChanges()per ottenere le IDentità appena salvate.

    Professionisti:

    Può usare l' intidentità.

  2. Usa client generato ID- Solo GUID.

    Pro: minimizzazione delle SaveChangesoperazioni. In grado di inserire un grande grafico di nuovi oggetti per un'operazione.

    Contro:

    Consentito solo per GUID


1

Quando si utilizza prima il codice EF 6.x.

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

e inizializzare una tabella di database, metterà a

(newsequentialid())

all'interno delle proprietà della tabella sotto l'intestazione Valore predefinito o Binding, consentendo all'ID di essere popolato al momento dell'inserimento.

Il problema è se si crea una tabella e si aggiunge

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

parte in seguito, i futuri database di aggiornamento non aggiungeranno nuovamente (newsequentialid ())

Correggere il modo corretto è cancellare la migrazione, eliminare il database e ripetere la migrazione ... oppure puoi semplicemente aggiungere (newsequentialid ()) nel designer della tabella.


Puoi approfondire dove va newsequentialid ()? Ho già modelli di database creati a mano, non usando prima il codice EF, e non riempie l'id perché non è la mia chiave primaria. Mi piacerebbe trovare una soluzione per questo.
Josh

1
@josh Supponendo che il codice sia prima di tipo Guid, fai clic con il pulsante destro del mouse sulla tabella in Sql Server Management Studio, fai clic sulla colonna Id e nella scheda Proprietà colonna, all'interno di (Generale), vedrai Valore predefinito o Binding. Se si creano tabelle DB manualmente, fare riferimento a NewSequentialId o NewId . Il caso d'uso generale è qualcosa di similewhen -column- is NULL, then NEWID()
Jeff Li
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.