我有一个表结构,它嵌套到5个层次,一个到多个关系向下。我想知道将这种数据保存到Server中的有效方法是什么。我现在循环每个子对象(C#)并运行一个insert,如果数据很大,插入就会变慢。
在传统的C#中是否有一种直接将ADO.NET传递给ADO.NET的方法?我有一个自定义框架,它为每个insert触发一个SQL脚本,它从对象属性中获取值。我不能转移到EF或NHirbernate,因为这是一个现有的项目。
我已经看到了将C#对象插入到DataTables中然后传递给SQl的方法,这是一种有效的方法吗?
请给我建议。
发布于 2014-09-15 00:10:24
我假设您从数据库的角度来看有这样的东西
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);
为每个子项目生成一个插入项。如果你有很多孩子,这真的可以减缓应用程序的速度。
在这种情况下,我将使用(并且已经使用)一个自定义sql服务器类型和一个存储过程来将整个事件保存在一个调用中。
您需要创建一个与表匹配的类型:
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
现在,这是从Server端执行的。现在转到C#侧。你需要做两件事:
第一种方法可以使用类似于这的东西(我使用这,这基本上是相同的),只需一个简单的
var items = root.Flatten(i => i.Children);
要做第二件事,首先需要将Server类型声明为datatable:
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);
}
并将它们附加到一个应该是SqlParameter
类型的SqlDbType.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();
}
应该是这样的。
发布于 2014-09-15 00:10:09
是的,如果希望将Dataset对象存储在DataBase中,可以使用选项,比如创建一个SQL UserDefinedType对象。在存储过程中填充对象、requierd值和read值,并使用您可以存储在Db中的业务逻辑填充Temp中的对象值。
https://stackoverflow.com/questions/25842909
复制相似问题