【发布时间】:2014-12-14 19:23:26
【问题描述】:
给定的业务对象类似于:
public class MyBase
{
public int Id { get; set; }
}
public class Parent : MyBase
{
public List<Child> Children { get; set; }
// Additional objects with 1:1 relationship
}
public class Child : MyBase
{
public Parent Parent { get; set; }
public List<Grandchild> Grandchildren { get; set; }
// Some other properties
}
public class GrandChild : MyBase
{
public Child { get; set; }
// Some other properties including a timestamp
}
由于poor performance of EF in this scenario,我正在尝试用 ADO.Net 和存储过程替换最初使用 Entity Framework 编写的批量插入功能。
不是数据库专家,我首先定位自己
http://www.sommarskog.se/arrays-in-sql-2008.html
使用该指导,我能够创建一个性能良好(相对于 EF)的存储过程,该存储过程插入 Child 及其 List<GrandChild>。
CREATE TYPE tvpInt32List AS TABLE (n int NOT NULL)
CREATE PROCEDURE uspInsertChild @parentId INT, @fk1Id INT, @fk2Id INT,
@listValues tvpInt32List READONLY
AS
DECLARE @id INT
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO dbo.Children VALUES(@fk2Id, @fk1Id, NULL, 0, 1, NULL, NULL, NULL, NULL, NULL, @fk1Id, @parentId)
SET @Id = SCOPE_IDENTITY()
INSERT INTO dbo.Grandchildren SELECT n, '', GETDATE(), @id FROM @listValues
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH
但是,我想更进一步,创建一个接受 Parent 对象数据的存储过程,然后为每个 Child 创建关联的 List<Child> 和 List<GrandChild>。
我在概念上不知道如何在存储过程中处理它。
我可以使用什么策略来传入该类型的数据结构并在存储过程中对其进行处理?
【问题讨论】:
-
Erland Sommarskog's的文章还是很不错的。通过将对象图作为 XML 传递,我们获得了最佳性能。表值参数更简洁但速度较慢。
-
我喜欢 Andromar 的建议,您可以很容易地使用
SELECT将 Children 和 Grandchildren 作为 XML 抓取来遍历分层 XML(好文章 here),然后将整个混乱发送到等待的 sproc有一个xml类型的输入参数。 -
@Andomar:Erland 指出 XML 可能比 TVP 慢很多。导入现在运行 3 小时(使用 EF 为 8 小时),所以我希望每一个性能优势都成为可能(数据将在未来 2-3 年内显着增长,因此运行时间会增加)。 sommarskog.se/arrays-in-sql-2005.html#XML
-
哦,我以为您正在寻找优化网页加载 :) 对于大量数据,请查看 SqlBulkCopy 这无需存储过程即可工作,并且需要目标服务器上的管理员权限,但速度非常快
-
似乎 SqlBulkCopy 一次只能在一张表上工作。 stackoverflow.com/q/6442035/141172 虽然,该问题的公认答案确实指向了一个可能的解决方案。
标签: sql-server sql-server-2008 stored-procedures