2010-03-31 29 views
14

Il mio progetto attuale consiste di 3 livelli standard: dati, business e presentazione. Vorrei utilizzare le entità dati per tutte le mie esigenze di accesso ai dati. Parte della funzionalità dell'app sarà la necessità di copiare tutti i dati all'interno di un file flat in un database. Il file non è così grande, quindi posso usare SqlBulkCopy. Ho trovato diversi articoli riguardanti l'uso della classe SqlBulkCopy in .NET. Tuttavia, tutti gli articoli utilizzano DataTable per spostare i dati avanti e indietro.SqlBulkCopy ed Entity Framework

C'è un modo per utilizzare le entità dati insieme a SqlBulkCopy o devo usare DataTable?

risposta

1

È possibile considerare un set di dati come una serializzazione dell'entità dati. Comunque, in generale, penso che SqlBulkCopy sia una cosa da tavolo a tabella, da qui il motivo Per i datatables.

1

SqlBulkCopy utilizza un IDataReader quando chiama il metodo WriteToServer in modo da poter implementare IDataReader in base a una raccolta IEnumerable. Ciò consentirebbe di prendere in un set di entità e chiamare SqlBulkCopy utilizzando l'implementazione IDataReader.

19

È necessario convertire le entità in IDataReader o DataTable.

C'è una piccola classe di supporto progettato per assistere con con: http://archive.msdn.microsoft.com/LinqEntityDataReader/Release/ProjectReleases.aspx?ReleaseId=389

EDIT: Link msdn è rotto, copia alt può essere trovato qui: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs

quindi è possibile utilizzare SqlBulkCopy in questo modo:

var sbCopy= new SqlBulkCopy(connectionString); 
sbCopy.DestinationTableName = "TableName"; 
sbCopy.WriteToServer(entitiesList.AsDataReader()); 
+0

viene interrotto il collegamento –

+2

@JonBarker - Ecco il link GitHub: https://github.com/matthewschrager/Repository/blob/master/Repository.EntityFramework/EntityDataReader.cs – DaveHogan

+0

@DaveHogan Mi piace l'idea che hai qui. Stiamo seminando oltre 200.000 articoli ed è doloroso per non dire altro. Ho provato a inserirlo nel nostro seeding EF di repo, ma quando creo un elemento di Office che ha un oggetto figlio di dire Address, non creerà gli elementi figlio o la relazione. Questo tipo di cose è possibile o va oltre lo scopo del codice collegato? Grazie – Jon

5

Abbiamo provato e testato un paio di approcci quando si inserisce massa utilizzando EF e alla fine siamo andati con i parametri con valori di tabella per ottenere ° La migliore prestazione in una gamma di dimensioni di riga. Non ho i numeri a portata di mano, ma so che questo Performance of bcp/BULK INSERT vs. Table-Valued Parameters è stato un fattore guida.

Inizialmente utilizzato SqlBulkCopy abbinato a un adattatore che ha preso un IEnumerable<T> e creato un IDataReader. Ha anche generato i metadati pertinenti per SqlBulkCopy. Il vantaggio qui è che l'importazione è una cosa solo di codice. Il codice che @davehogan ha pubblicato è stato usato come base per questo.

I parametri con valori di tabella richiedono una stored procedure e un tipo di tabella definito nel database. Se stai usando il codice, puoi eseguire SQL per crearli come parte dello script di creazione. Mentre questo è più lavoro, abbiamo scoperto che abbiamo ottenuto un throughput significativamente più consistente e più veloce di righe nel database.

Inoltre, vale la pena considerare non inserimento di massa nella tabella principale. Usiamo una tabella di heap temporaneo e aggiungiamo un indice cluster ad esso una volta che i dati vengono importati. Quindi eseguiamo un MERGE tra la tabella temporanea e la tabella principale. Questo ha il vantaggio di non bloccare l'indice della tabella principale mentre si inserisce e migliora la concorrenza. Tendiamo a salire di 2500 righe/sec per CPU inserita usando questo metodo.

Fatemi sapere se volete maggiori informazioni.

0

SqlBulkCopy è un trasferimento diretto, quasi byte-array, di dati di riga dal client a SQL Server. È facilmente il modo più efficiente per ottenere dati in SQL Server.

La sua prestazione si trova in operazioni veramente "di massa", tuttavia. Centinaia o migliaia di righe non sono necessariamente abbastanza alte da giustificare l'uso.Decine di migliaia o milioni di righe sono state le prestazioni di SqlBulkCopy brilleranno davvero. E, alla fine, tutto ciò di cui stiamo veramente parlando è ottenere i dati sul server.

Ci sono altre sfide significative nell'ottenere un set di righe nella tabella di un database di produzione. Reindirizzamento, riordino (se esiste un indice cluster), convalida della chiave esterna, tutti questi tipi di cose aggiungono tempo all'inserimento e sono potenzialmente bloccanti per tabelle e indici.

Inoltre, i dati TVP vengono scritti sul disco (come dati della tabella temporanea) e quindi sono accessibili per essere inseriti nelle tabelle. SqlBulkCopy è in grado di andare direttamente al tuo tavolo ... le prestazioni in quel caso sono significativamente più veloci, tuttavia, è necessario bilanciare la velocità per la concorrenza.

Penso che la regola generale sia, se si dispone di una manciata di righe da gestire, pensare a TVP e se si dispone di molte migliaia di righe, prendere in considerazione l'accesso a SQL Server il più rapidamente possibile tramite SqlBulkCopy.

-2

Come complemento @DaveHogan risposta,

V'è ora nuove librerie che permettono l'esecuzione di Inserimento di massa (utilizzando SqlBulkCopy sotto il cofano) per Entity Framework utilizzando entità di dati invece di DataTable.

Diniego: Sono il titolare del progetto Entity Framework Extensions

Questa libreria non è libero, ma consente di eseguire con facilità:

  • BulkSaveChanges
  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge

Sotto il cofano, viene utilizzato SqlBulkCopy. L'utilizzo del metodo di estensione make è molto più semplice/più veloce della codifica di una soluzione personalizzata per ogni Bulk Insert da utilizzare.

Esempio

// Easy to use 
context.BulkSaveChanges(); 

// Easy to customize 
context.BulkSaveChanges(bulk => bulk.BatchSize = 100); 

scarso rendimento

Mi dispiace che si stanno ottenendo scarso rendimento,

Assicurarsi che non stanno includendo il tempo da qualche errore comune come dimenticare di Compilare JIT, usando Aggiungi invece di AddRange che ha un impatto sulle prestazioni del test ma non è correlato alla nostra libreria.

La maggior parte delle persone dichiara di ottenere un miglioramento delle prestazioni 25-50 volte escludendo tutti gli errori di benchmark delle prestazioni comuni.

Vedi: Entity Framework Extensions - Benchmark

+0

scarso rendimento –

+0

Ciao @Ashraf, facci sapere perché tu dici scarse prestazioni. Normalmente è causato da un errore comune non correlato alla nostra libreria come l'utilizzo di Aggiungi oltre AddRange –

+1

Scusa, errore mio. dobbiamo disabilitare la cache di tracciamento. –

1

È possibile utilizzare Bulk package biblioteca. La versione Bulk Insert 1.0.0 viene utilizzata in progetti con Entity framework> = 6.0.0. più Descrizione può essere trovato in seguito link- Bulkoperation source code