Come ottenere di nuovo EF in Sync con il codice senza perdere i dati quando Update-database restituisce il seguente messaggio
Messaggio di errore: System.Data.SqlClient.SqlException (0x80131904): esiste già un oggetto denominato "" nel database.
Inizialmente ho scritto questo come una domanda di auto-risposta, poiché avevo lottato con il problema per qualche tempo, come alcuni colleghi, ma sfortunatamente la mia risposta è stata cancellata e non posso recuperarla.
Poiché è una situazione che sospetto possa accadere più volte mentre le persone cercano di "ripulire" le vecchie migrazioni, ho pensato di documentarlo con le istruzioni passo passo.
Descrizione della situazione in cui ci siamo trovati : Non abbiamo potuto non creare un nuovo database locale perché lo script di inizializzazione era incompleto e non è stato possibile applicare gli aggiornamenti al database di produzione perché gli script di migrazione creano tabelle già esistenti. E non volevamo cancellare i dati di produzione.
Sintomo : impossibile eseguire Update-Database perché sta tentando di eseguire lo script di creazione e il database contiene già tabelle con lo stesso nome.
Messaggio di errore: System.Data.SqlClient.SqlException (0x80131904): esiste già un oggetto denominato "" nel database.
Problema di fondo : per capire meglio questo aspetto, ti consiglio di guardare entrambi i video di riferimento qui: https://msdn.microsoft.com/en-us/library/dn481501(v=vs.113).aspx
Per riassumere, EF comprende dove si trova il database corrente rispetto a dove si trova il codice in base a una tabella nel database denominata dbo .__ MigrationHistory. Quando esamina gli script di migrazione, prova a riconciliarsi dove era l'ultimo con gli script. Se non può, cerca semplicemente di applicarli in ordine. Ciò significa che ritorna allo script di creazione iniziale e se si guarda la prima parte del comando UP, sarà CreeateTable per la tabella in cui si è verificato l'errore.
Soluzione : ciò che dobbiamo fare è ingannare l'EF nel pensare che il database corrente sia aggiornato, mentre "non" applicare questi comandi CreateTable poiché il database di produzione esiste già. Una volta impostato il DB di produzione, dobbiamo comunque essere in grado di creare anche database locali.
Passaggio 1: DB di produzione pulito Per prima cosa, eseguire un backup del db di produzione. In SSMS, fare clic con il pulsante destro del mouse sul database, selezionare "Attività> Esporta applicazione livello dati ..." e seguire le istruzioni. Aprire il database di produzione ed eliminare / eliminare la tabella dbo .__ MigrationHistory.
Passaggio 2: Pulizia dell'ambiente locale Aprire la cartella delle migrazioni ed eliminarla. Suppongo che tu possa riprenderti tutto da Git se necessario.
Passaggio 3: Ricreazione iniziale In Gestione pacchetti, eseguire "Abilita-Migrazioni" (EF ti chiederà di usare -ContextTypeName se hai più contesti). Esegui "Add-Migration Initial -verbose". Questo creerà lo script iniziale per creare il database da zero in base al codice corrente. Se nel precedente Configuration.cs erano presenti operazioni di seed, copiarlo.
Step 4: Trick EF A questo punto, se avessimo eseguito Update-Database , avremmo avuto l'errore originale. Quindi, dobbiamo ingannare EF per pensare che sia aggiornato, senza eseguire questi comandi. Quindi, vai nel metodo Up nella migrazione iniziale che hai appena creato e commenta tutto.
Passaggio 5: Database di aggiornamento Senza codice da eseguire nel processo Up, EF creerà la tabella dbo .__ MigrationHistory con la voce corretta per dire che ha eseguito correttamente questo script. Vai e dai un'occhiata se vuoi. Ora, decommenta quel codice e salva. È possibile eseguire nuovamente il database di aggiornamento se si desidera verificare che EF ritenga aggiornato. Non eseguirà il passo Up con tutti i comandi CreateTable perché pensa che lo abbia già fatto.
Passaggio 6: Confermare che EF è ATTUALMENTE aggiornato Se avevi un codice a cui non erano ancora state applicate migrazioni, questo è ciò che ho fatto ...
Esegui "Add-Migration MissingMigrations" Questo creerà praticamente uno script vuoto. Poiché il codice era già presente, in realtà c'erano i comandi corretti per creare queste tabelle nello script di migrazione iniziale, quindi ho semplicemente tagliato CreateTable e comandi di rilascio equivalenti nei metodi Su e Giù.
Ora, eseguire di nuovo il database di aggiornamento e guardarlo eseguire il nuovo script di migrazione, creando le tabelle appropriate nel database.
Passaggio 7: riconferma e conferma. Costruisci, prova, corri. Assicurarsi che tutto sia in esecuzione, quindi confermare le modifiche.
Step 8: Lascia che il resto della tua squadra sappia come procedere. Quando la prossima persona si aggiorna, EF non saprà cosa l'ha colpito dato che gli script che aveva eseguito prima non esistono. Ma, supponendo che i database locali possano essere spazzati via e ricreati, va tutto bene. Dovranno abbandonare il loro database locale e aggiungerlo di nuovo da EF. Se avessero cambiamenti locali e migrazioni in sospeso, raccomanderei loro di creare nuovamente il loro DB su master, passare al loro branch di funzionalità e ricreare questi script di migrazione da zero.