我看了一些相关主题,但我的问题没有得到很好的回答:
在我的Web应用程序的代码中运行存储过程时,我有以下类型的设置。问题是我现在面临着插入多个产品的可能性,我想在一个ExecuteNonQuery
中完成所有操作,而不是foreach loop
并且运行n
次。
我不确定如何使用我当前的设置执行此操作,或者是否可以执行此操作。
代码应该有点自我解释,但如果需要澄清,请告诉我。感谢。
SqlDatabase database = new SqlDatabase(transMangr.ConnectionString);
DbCommand commandWrapper = StoredProcedureProvider.GetCommandWrapper(database, "proc_name", useStoredProc);
database.AddInParameter(commandWrapper, "@ProductID", DbType.Int32, entity._productID);
database.AddInParameter(commandWrapper, "@ProductDesc", DbType.String, entity._desc);
...more parameters...
Utility.ExecuteNonQuery(transMangr, commandWrapper);
PROC
ALTER PROCEDURE [dbo].[Products_Insert]
-- Add the parameters for the stored procedure here
@ProductID int,
@Link varchar(max)
@ProductDesc varchar(max)
@Date DateTime
AS BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[Prodcuts]
(
[CategoryID],
[Link],
[Desc],
[Date]
)
VALUES
(
@ProductID,
@Link,
@ProductDesc,
@Date
)
END
答案 0 :(得分:1)
您应该在循环中运行存储过程。只要确保你很少提交,而不是在每次插入后提交。
对于替代方案,您已经找到了有关加载数据的讨论。
就个人而言,我喜欢insert into myTable (select *, literalValue from someOtherTable);
形式的SQL批量插入
但在你的情况下,这可能不会做。
答案 1 :(得分:0)
您可以将所有数据作为表值参数传递 - MSDN对此有一个很好的解释here
以下内容应该有效
CREATE TABLE dbo.tSegments
(
SegmentID BIGINT NOT NULL CONSTRAINT pkSegment PRIMARY KEY CLUSTERED,
SegCount BIGINT NOT NULL
);
CREATE TYPE dbo.SegmentTableType AS TABLE
(
SegmentID BIGINT NOT NULL
);
CREATE PROCEDURE dbo.sp_addSegments
@Segments dbo.SegmentTableType READONLY
AS
BEGIN
MERGE INTO dbo.tSegments AS tSeg
USING @Segments AS S
ON tSeg.SegmentID = S.SegmentID
WHEN MATCHED THEN UPDATE SET T.SegCount = T.SegCount + 1
WHEN NOT MATCHED THEN INSERT VALUES(tSeg.SegmentID, 1);
END
答案 2 :(得分:0)
为循环外的命令定义commandWrapper和参数,然后在循环中只分配参数值并执行proc。
SqlDatabase database = new SqlDatabase(transMangr.ConnectionString);
DbCommand commandWrapper = StoredProcedureProvider.GetCommandWrapper(database, "proc_name", useStoredProc);
database.AddInParameter(commandWrapper, "@ProductID", DbType.Int32 );
database.AddInParameter(commandWrapper, "@ProductDesc", DbType.String);
...more parameters...
foreach (var entity in entitties)
{
database.SetParameterValue(commandWrapper, "@ProductID",entity._productID);
database.SetParameterValue(commandWrapper, "@ProductDesc",entity._desc);
//..more parameters...
Utility.ExecuteNonQuery(transMangr, commandWrapper);
}
答案 3 :(得分:0)
从纯粹的处理方式来看并不理想,但是有时会受到框架和库的限制,并且您被迫以某种方式调用存储过程,以某种方式绑定参数,并且连接由管理池作为框架的一部分。
在这种情况下,我们发现一种有效的方法是简单地编写带有许多参数的存储过程,这些参数通常是名称,后跟数字,例如@ ProductId1,@ ProductDesc1,@ ProductId2,@ ProductDesc2,直到您决定的数字,可能是32。
您可以使用某种形式的脚本语言来为此生成代码行。
您可以获取存储过程,以首先将所有值插入允许空值的表参数中,然后以类似于Johnv2020的答案的方式对此数据进行批量插入/合并。您可以先删除空行。
通常一次完成效率更高(部分原因是数据库操作本身,部分原因是框架在连接调用过程中的开销等)