如何将 .NET 对象集合(父子)层次结构传递给 SQL Server 存储过程
Posted
技术标签:
【中文标题】如何将 .NET 对象集合(父子)层次结构传递给 SQL Server 存储过程【英文标题】:How to pass .NET Collection of objects (Parent-Child) hierarchy to a SQL Server stored procedure 【发布时间】:2016-12-23 17:20:32 【问题描述】:我需要将 .NET 集合传递给存储过程。我的收藏包含 1000 条记录。每条记录包含2-3个其他类型的子对象。
我只需要通过从 .NET 调用存储过程来一次插入它们。
我已经尝试过 TVP(表值参数),但这根本无法满足我的需求。
对于每个根级记录,我需要通过传递根记录及其对应的子记录来调用存储过程。这使得整个过程非常缓慢。
这就是为什么我正在寻找一种方法,以便我可以一次传递整个层次结构列表,并且在存储过程中,通过循环和迭代子记录,我可以插入父子记录。
我怎样才能做到这一点?
【问题讨论】:
尝试使用 XML 并将其解压到存储过程中的临时表中。它对我来说工作得很快。 表值参数是一个很好的方法。只需传递 2 个表,一个用于父级,另一个用于子级,并使用一些键来关联它们。 @Alejandro :目前,我以几乎相同的方式通过。而是将整个父级作为一张表传递,将整个子级作为另一张表传递,我正在传递一个父级记录及其对应的子级列表。但这真的很慢,因为我需要插入 100K 父记录。此外,对于每个单亲父母,都有 3-4 个孩子与之关联。 这可能是问题的根源。尝试一次完成所有这些,而不是一个接一个。我想大部分开销来自重复的网络往返而不是查询本身。 是的,这就是我所知道的。所以,解决方案是一次传递整个层次结构,然后让 SQL 在内部完成。所以问题归结为:如何一次传递整个层次结构(例如 List我实际上是在 3 周前才这样做的。
-
创建一个“临时”关联键(我使用 GUID)将父级和子级链接在一起,因为您没有数据库 ID(临时键永远不会保存在数据库中)
调用 TVP 存储过程。在两个单独的表变量中传递所有父母和所有孩子
创建临时表或表 var 来存储临时 ID/数据库 ID 关系
使用带有 OUTPUT 的 merge 语句将 Inserted.Id 值和 temp id 获取到步骤 3 中创建的临时表中
使用 CTE 和合并语句使用父记录中的实际 DB id 插入子记录
这里有几个关于该过程的链接以及“真实”示例:
merge parent and child SQL Server tables
T-SQL - Insert Data into Parent and Child Tables
【讨论】:
Keith : 你能告诉我如何将父子层次列表从 .NET 传递到存储过程吗?我不想在传递整个列表时打破父子层次结构。因为,以后很难将每个子实体与其对应的父实体关联起来。 我已经在我的答案中编写了代码示例(此链接中的第二个链接),但仅限于 sql 部分。您需要 .net 端示例吗? 是的,如果你能管理详细的答案,那就太好了:-) @Usman 你知道如何从你的列表中填充数据表吗? 是的,我知道如何在 c# 中填充数据表以将其作为 TVP 传递给存储过程【参考方案2】:您可以使用 XML 将记录及其子项传递给存储过程。例如
DECLARE @xml XML = '<root>
<parent value="213">
<child childValue="1111"></child>
<child childValue="1112"></child>
</parent>
<parent value="2313">
<child childValue="3333"></child>
<child childValue="3332"></child>
</parent>
</root>'
然后你可以做很多方法,其中之一是对记录进行非规范化并保存到临时表以供进一步处理
SELECT
T.c.value('parent::*/@value', 'INT') AS ParentValue,
T.c.value('@childValue', 'INT') AS ChildValue
FROM @xml.nodes('/root[1]/parent/child') T(c)
结果会是这样的
ParentValue ChildValue
213 1111
213 1112
2313 3332
2313 3333
【讨论】:
很抱歉,我根本无法使用 XML。这在应用程序中是额外开销的。我一次处理 10 万条记录,并在内存 xml 中构建包含 80 列包含 10 列子项的单父记录,这将是一个非常糟糕的主意。以上是关于如何将 .NET 对象集合(父子)层次结构传递给 SQL Server 存储过程的主要内容,如果未能解决你的问题,请参考以下文章