将 C# 嵌套对象保存到 SQL 服务器的有效方法
本文关键字:服务器 有效 方法 SQL 嵌套 对象 保存 | 更新日期: 2023-09-27 18:21:55
>我有一个嵌套到 5 个级别的表结构,具有向下的一对多关系。我想知道将此类数据保存到 SQL Server 中的有效方法是什么。我现在循环每个子对象 (C#( 并运行一个插入,如果数据很大,它会变慢。
有没有办法在传统 ADO.NET 中将 C# 直接传递给 SQL?我有一个自定义框架,它为每个插入触发一个 SQL 脚本,该脚本从对象属性中获取值。我无法迁移到 EF 或 NHirbernate,因为它是一个现有项目。
我已经看到了可以将 C# 对象插入到数据表中然后传递给 SQl 的方法,这是一种有效的方法吗?
请指教。
我假设从数据库的角度来看你有这样的东西
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
现在,这是从SQL Server端完成的。现在进入 C# 端。您需要做两件事:
- 将层次结构平展为列表
- 将该列表作为数据表发送到数据库
第一个可以使用这样的东西来完成(我使用这个,这基本上是相同的东西(,一个简单的
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();
}
而且,应该就是这样。
是的,如果您希望将数据集对象存储在数据库中,则可以使用以下选项:创建一个 SQL 用户定义类型对象。填充对象所需的值,并在存储过程中读取值,并在 Temp 中填充对象值,并使用业务逻辑存储在 DB 中。