È possibile recuperare gli ID di PrimayKey dopo un SQL BulkCopy?

c# sql sqlbulkcopy sql-server-2005

Domanda

Sto usando C # e utilizzo di SqlBulkCopy. Ho un problema però. Ho bisogno di fare un inserto di massa in una tabella, poi un altro inserimento di massa in un'altra tabella.

Questi 2 hanno una relazione PK / FK.

Table A
Field1 -PK auto incrementing (easy to do SqlBulkCopy as straight forward)

Table B
Field1 -PK/FK - This field makes the relationship and is also the PK of this table. It is not auto incrementing and needs to have the same id as to the row in Table A.

Quindi queste tabelle hanno una relazione uno a uno, ma non sono sicuro di come recuperare tutti quei PK Id che l'inserto di massa ha fatto da quando ne ho bisogno per la Tabella B.

modificare

Potrei fare qualcosa di simile?

SELECT * 
FROM Product
WHERE NOT EXISTS (SELECT * FROM ProductReview WHERE Product.ProductId = ProductReview.ProductId AND Product.Qty = NULL AND Product.ProductName != 'Ipad')

Questo dovrebbe trovare tutte le righe che sono appena state inserite con la copia bulk di sql. Non sono sicuro di come ottenere i risultati da questo, quindi fare un inserimento di massa con loro da un SP.

L'unico problema che posso vedere con questo è che se un utente sta facendo i record uno alla volta e questa dichiarazione viene eseguita allo stesso tempo, potrebbe provare a inserire una riga due volte nella "Tabella di controllo del prodotto".

Quindi dire che ho avuto l'impressione che un utente utilizzasse la modalità manuale e che un altro utente facesse il modo di massa all'incirca nello stesso momento.

modo manuale. 1. L'utente invia i dati 2. Linq a sql L'oggetto prodotto viene creato e compilato con i dati e inviato. 3. questo oggetto contiene ora il ProductId 4. Un altro oggetto da linq a sql viene creato per la tabella di revisione del prodotto e viene inserito (l'ID prodotto del passaggio 3 viene inviato insieme).

Modo di massa. 1. L'utente acquisisce i dati da un utente che condivide i dati. 2. Vengono afferrate tutte le righe di prodotto dell'utente di condivisione. 3. L'inserimento della copia bulk di SQL sulle righe del prodotto avviene. 4. My SP seleziona tutte le righe che esistono solo nella tabella Prodotto e soddisfa alcune altre condizioni. 5. Inserimento di massa avviene con tali righe.

Quindi, cosa succede se il passaggio 3 (modo manuale) avviene contemporaneamente alla fase 4 (modo di massa). Penso che proveresti a inserire la stessa riga due volte, causando un'espressione di vincolo primario.

Risposta accettata

In tale scenario, vorrei usare SqlBulkCopy per inserire in una tabella di staging (cioè una che assomiglia ai dati che voglio importare, ma non fa parte delle principali tabelle transazionali), e quindi al DB in un INSERT / SELECT per sposta i dati nella prima tabella reale.

Ora ho due scelte a seconda della versione del server; Potrei fare un secondo INSERT / SELECT alla seconda tabella reale, o potrei usare la clausola INSERT / OUTPUT per fare il secondo inserto, usando le righe di identità dalla tabella.

Per esempio:

     -- dummy schema
     CREATE TABLE TMP (data varchar(max))
     CREATE TABLE [Table1] (id int not null identity(1,1), data varchar(max))
     CREATE TABLE [Table2] (id int not null identity(1,1), id1 int not null, data varchar(max))

     -- imagine this is the SqlBulkCopy
     INSERT TMP VALUES('abc')
     INSERT TMP VALUES('def')
     INSERT TMP VALUES('ghi')

     -- now push into the real tables
     INSERT [Table1]
     OUTPUT INSERTED.id, INSERTED.data INTO [Table2](id1,data)
     SELECT data FROM TMP

Risposta esperta

Disclaimer : sono il proprietario del progetto C # Bulk Operations

La libreria supera le limitazioni di SqlBulkCopy e aggiunge funzionalità flessibili come il valore di identità inserito nell'output.

Dietro il codice, fa esattamente come la risposta accettata, ma molto più semplice da usare.

var bulk = new BulkOperation(connection);

// Output Identity
bulk.ColumnMappings.Add("ProductID", ColumnMappingDirectionType.Output);
// ... Column Mappings...

bulk.BulkInsert(dt);


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow