Manières efficaces d'save des objects nesteds C # sur le server SQL

J'ai une structure de table qui est nestede à 5 niveaux avec une relation un à plusieurs allant vers le bas. Je veux savoir ce qui est un moyen efficace de sauvegarder ce type de données dans SQL Server. Je boucle maintenant sur chaque object enfant (C #) et exécute une insertion qui devient lente si datatables sont grandes.

Y at-il un moyen de passer le C # directement à SQL dans ADO.NET traditionnel? J'ai un cadre personnalisé qui triggers un script SQL pour chaque insertion, qui récupère les valeurs des propriétés de l'object. Je ne peux pas passer à EF ou NHirbernate car c'est un projet existant.

J'ai vu des façons où les objects C # peuvent être insérés dans DataTables et ensuite transmis à SQl, est-ce un moyen efficace?

S'il vous plaît donnez votre avis.

Je suppose que vous avez quelque chose comme ça du sharepoint vue de la database

CREATE TABLE Items (ID INT -- primary key, Name VARCHAR(MAX), ParentID INT) -- foreign key that loops on the same table 

et un object comme celui-ci en C #

 public class Item { public int ID {get; set;} public ssortingng Name {get; set;} public int ParentID {get; set;} public Item Parent {get; set;} public List<Item> Children {get; set;} } 

et vous avez du code qui ressemble à:

 var root = MakeMeATree(); databaseSaver.SaveToDatabase(root); 

Cela génère un insert par item pour chaque enfant. Si vous avez beaucoup d'enfants, cela peut vraiment ralentir l'application.

Ce que j'utiliserais (et que j'aurais utilisé) dans ce cas est un type de server sql personnalisé et une procédure stockée pour sauvegarder le tout en un seul appel.

Vous devrez créer un type correspondant à la table:

 CREATE TYPE dbo.ItemType AS TABLE ( ID INT, Name VARCHAR(MAX), ParentID INT ); 

et une procédure simple qui utilise le type:

 CREATE PROCEDURE dbo.InsertItems ( @Items AS dbo.ItemType READONLY ) AS BEGIN INSERT INTO SampleTable(ID, Name, ParentID) SELECT ID, Name, ParentID From @Items END 

Maintenant, cela se fait du côté de SQL Server. Maintenant sur le côté C #. Vous devez faire deux choses:

  1. Aplatir la hiérarchie dans une list
  2. Envoyé cette list en tant que datatable à la database

Le premier peut être fait en utilisant quelque chose comme ça (j'utilise ceci , qui est fondamentalement la même chose), avec un simple

 var items = root.Flatten(i => i.Children); 

Pour faire la deuxième chose, vous devez d'abord déclarer le type de SQL Server en tant que datatable:

 DataTable dt = new DataTable("Items"); dt.Columns.Add("ID", typeof(int)); dt.Columns.Add("Name", typeof(ssortingng)); dt.Columns.Add("ParentID", typeof(int)); 

Ensuite, remplissez simplement les valeurs:

 foreach(var item in items) { dt.Rows.Add(item.ID, item.Name, item.ParentID); } 

et les attache à un SqlParameter , qui devrait être du type SqlDbType.Structured , comme ceci:

 using (var cmd = new SqlCommand("InsertItems", connection)) { cmd.CommandType = CommandType.StoredProcedure; var itemsParam = new SqlParameter("@Items", SqlDbType.Structured); itemsParam .Value = dt; cmd.Parameters.Add(itemsParam); cmd.ExecuteNonQuery(); } 

Et, ça devrait être ça.

Oui, si vous voulez que vos objects de jeu de données soient stockés dans la database, vous pouvez utiliser des options comme Créer un object SQL UserDefinedType. Remplissez l'object les valeurs requierd et lisez la valeur dans la procédure stockée ET Remplissez la valeur de l'object dans le Temp et en utilisant votre logique métier vous pouvez stocker dans Db.