Quelle est la meilleure façon d'insert rapidement des données SQL et des lignes dépendantes?

J'ai besoin d'écrire du code pour insert environ 3 millions de lignes de données.
Dans le même time, j'ai besoin d'insert le même nombre de lignes de compagnon.

C'est à dire que le schéma ressemble à ceci:

Item - Id - Title Property - Id - FK_Item - Value 

Ma première tentative a été quelque chose de vaguement comme ceci:

 BaseDataContext db = new BaseDataContext(); foreach (var value in values) { Item i = new Item() { Title = value["title"]}; ItemProperty ip = new ItemProperty() { Item = i, Value = value["value"]}; db.Items.InsertOnSubmit(i); db.ItemProperties.InsertOnSubmit(ip); } db.SubmitChanges(); 

Évidemment, c'était terriblement lent alors j'utilise quelque chose comme ça:

 BaseDataContext db = new BaseDataContext(); DataTable dt = new DataTable("Item"); dt.Columns.Add("Title", typeof(ssortingng)); foreach (var value in values) { DataRow item = dt.NewRow(); item["Title"] = value["title"]; dt.Rows.Add(item); } using (System.Data.SqlClient.SqlBulkCopy sb = new System.Data.SqlClient.SqlBulkCopy(db.Connection.ConnectionSsortingng)) { sb.DestinationTableName = "dbo.Item"; sb.ColumnMappings.Add(new SqlBulkCopyColumnMapping("Title", "Title")); sb.WriteToServer(dt); } 

Mais cela ne me permet pas d'append les lignes 'Property' correspondantes.

Je pense que la meilleure solution pourrait être d'append une procédure stockée comme celle-ci qui me permet généralement de faire une insertion en bloc (ou au less plusieurs insertions, mais je peux probablement désactiver la journalisation dans la procédure stockée) ids correspondants.

Quelqu'un peut-il penser à une meilleure solution (c'est-à-dire plus succincte, à performance presque égale)?

Pour combiner les deux meilleures réponses précédentes et append la pièce manquante pour les ID:

1) Utilisez BCP pour charger datatables dans une table temporaire "staging" définie comme ceci

 CREATE TABLE stage(Title AS VARCHAR(??), value AS {whatever}); 

et vous aurez besoin de l'index approprié pour les performances plus tard:

 CREATE INDEX ix_stage ON stage(Title); 

2) Utilisez SQL INSERT pour charger la table Item:

 INSERT INTO Item(Title) SELECT Title FROM stage; 

3) Enfin charger la table de propriété en joignant la scène avec l'article:

 INSERT INTO Property(FK_ItemID, Value) SELECT id, Value FROM stage JOIN Item ON Item.Title = stage.Title 

La meilleure façon de déplacer autant de données dans SQL Server est bcp. En supposant que datatables commencent dans une sorte de file, vous devrez écrire un petit script pour canaliser datatables dans les deux tables. Alternativement, vous pouvez utiliser bcp pour canaliser datatables dans une table unique, puis utiliser un SP pour insert datatables dans les deux tables.

Copiez en bloc datatables dans une table temporaire, puis appelez un proc stocké qui divise datatables dans les deux tables que vous devez remplir.

Vous pouvez également copyr en bloc du code en utilisant la class .NET SqlBulkCopy.