将C#嵌套对象保存到SQL Server的有效方法

时间:2014-09-15 07:33:42

标签: c# sql-server

我有一个表结构,它嵌套到5个级别,一对多关系向下。 我想知道将这种数据保存到SQL Server中的有效方法。我现在循环每个子对象(C#)并运行一个插入,如果数据很大,它会变慢。

有没有办法在传统的ADO.NET中将C#直接传递给SQL?我有一个自定义框架,它为每个插件触发一个SQL脚本,该脚本从对象属性中获取值。我不能转移到EF或NHirbernate,因为它是一个现有的项目。

我已经看过C#对象可以插入到DataTables然后传递给SQl的方法,这是一种有效的方法吗?

请告知。

2 个答案:

答案 0 :(得分:6)

我假设从数据库的角度来看你有这样的东西

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

和C#中的这样一个对象

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

你有一些看起来像的代码:

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

为每个孩子生成一个insert-per-item。如果您有很多孩子,这可能会使应用程序变慢。

在这种情况下,我将使用(并且已经使用过的)是一个自定义的sql server类型和一个存储过程,用于在一次调用中保存整个内容。

您需要创建一个与表匹配的类型:

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

和使用类型的简单过程:

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

现在,这是从SQL Server端进行的。现在进入C#方面。你需要做两件事:

  1. 将层次结构展平为列表
  2. 将该列表作为数据表发送到数据库
  3. 第一个可以使用像this这样的东西(我使用this,基本上是一样的东西),用简单的

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

    要做的第二件事,首先需要将SQL Server类型声明为数据表:

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

    接下来,只需填写值:

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

    并将其附加到SqlParameterSqlDbType.Structured类型,如下所示:

    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();
    }
    

    而且,应该是它。

答案 1 :(得分:-1)

是的,如果您希望数据集对象存储在数据库中,您可以使用类似选项 创建SQL UserDefinedType对象。 在对象中填充需要的值并在存储过程中读取值并在Temp中填充对象值并使用您可以存储在Db中的业务逻辑。