我有一个表结构,它嵌套到5个级别,一对多关系向下。 我想知道将这种数据保存到SQL Server中的有效方法。我现在循环每个子对象(C#)并运行一个插入,如果数据很大,它会变慢。
有没有办法在传统的ADO.NET中将C#直接传递给SQL?我有一个自定义框架,它为每个插件触发一个SQL脚本,该脚本从对象属性中获取值。我不能转移到EF或NHirbernate,因为它是一个现有的项目。
我已经看过C#对象可以插入到DataTables然后传递给SQl的方法,这是一种有效的方法吗?
请告知。
答案 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#方面。你需要做两件事:
第一个可以使用像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);
}
并将其附加到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();
}
而且,应该是它。
答案 1 :(得分:-1)
是的,如果您希望数据集对象存储在数据库中,您可以使用类似选项 创建SQL UserDefinedType对象。 在对象中填充需要的值并在存储过程中读取值并在Temp中填充对象值并使用您可以存储在Db中的业务逻辑。