我想知道有没有办法进行批量更新?我正在使用ms sql server 2005。
我看到了sqlDataAdaptor,但似乎你必须首先使用它来选择语句,然后填充一些数据集并对数据集进行更改。
现在我正在使用linq to sql来进行选择,所以我想尝试保持这种方式。然而,进行大规模更新太慢了。那么我可以将我的linq保存到sql(对于选择部分)但使用不同的东西来进行批量更新吗?
由于
修改
我对这种临时表方式感兴趣,但我不知道怎么做,仍然不清楚它会如何更快,因为我不明白更新部分是如何工作的。
那么有人能告诉我这将如何工作以及如何处理并发连接?
EDIT2
这是我尝试使用xml进行批量更新的最新尝试,但它使用了大量资源,而我的共享主机不允许它通过。所以我需要一种不同的方式,这就是为什么我没有查看临时表。
using (TestDataContext db = new TestDataContext())
{
UserTable[] testRecords = new UserTable[2];
for (int count = 0; count < 2; count++)
{
UserTable testRecord = new UserTable();
if (count == 1)
{
testRecord.CreateDate = new DateTime(2050, 5, 10);
testRecord.AnotherField = true;
}
else
{
testRecord.CreateDate = new DateTime(2015, 5, 10);
testRecord.AnotherField = false;
}
testRecords[count] = testRecord;
}
StringBuilder sBuilder = new StringBuilder();
System.IO.StringWriter sWriter = new System.IO.StringWriter(sBuilder);
XmlSerializer serializer = new XmlSerializer(typeof(UserTable[]));
serializer.Serialize(sWriter, testRecords);
using (SqlConnection con = new SqlConnection(connectionString))
{
string sprocName = "spTEST_UpdateTEST_TEST";
using (SqlCommand cmd = new SqlCommand(sprocName, con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter param1 = new SqlParameter("@UpdatedProdData", SqlDbType.VarChar, int.MaxValue);
param1.Value = sBuilder.Remove(0, 41).ToString();
cmd.Parameters.Add(param1);
con.Open();
int result = cmd.ExecuteNonQuery();
con.Close();
}
}
}
@ Fredrik Johansson我不确定你说的是什么。就像在我看来,你希望我为每条记录做一个更新声明。我不能这样做,因为我需要更新1到50,000+记录,直到那时我才知道。
编辑3
所以现在这是我的SP。我认为它应该能够并发连接,但我想确保。
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_MassUpdate]
@BatchNumber uniqueidentifier
AS
BEGIN
update Product
set ProductQty = 50
from Product prod
join StagingTbl stage on prod.ProductId = stage.ProductId
where stage.BatchNumber = @BatchNumber
DELETE FROM StagingTbl
WHERE BatchNumber = @BatchNumber
END
答案 0 :(得分:2)
您可以使用sqlDataAdapter进行批量更新。不管你如何填充你的数据集都没关系。 L2SQL或其他什么,您可以使用不同的方法来进行更新。只需使用数据表中的数据定义要运行的查询。
这里的关键是UpdateBatchSize。 dataadapter将以您定义的任何大小批量发送更新。您需要使用此值过期以查看哪个数字效果最佳,但典型数字500-1000最佳。然后,SQL可以优化更新并以更快的速度执行。请注意,在执行batchupdates时,无法更新数据表的行源。
我使用此方法进行10-100K的更新,它通常在2分钟内运行。这取决于你正在更新的内容。
抱歉,这是在VB ......。
Using da As New SqlDataAdapter
da.UpdateCommand = conn.CreateCommand
da.UpdateCommand.CommandTimeout = 300
da.AcceptChangesDuringUpdate = False
da.ContinueUpdateOnError = False
da.UpdateBatchSize = 1000 ‘Expirement for best preformance
da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 'Needed if UpdateBatchSize > 1
sql = "UPDATE YourTable"
sql += " SET YourField = @YourField"
sql += " WHERE ID = @ID"
da.UpdateCommand.CommandText = sql
da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None
da.UpdateCommand.Parameters.Clear()
da.UpdateCommand.Parameters.Add("@YourField", SqlDbType.SmallDateTime).SourceColumn = "YourField"
da.UpdateCommand.Parameters.Add("@ID", SqlDbType.SmallDateTime).SourceColumn = "ID"
da.Update(ds.Tables("YourTable”)
End Using
另一种选择是批量复制到临时表,然后运行查询以从中更新主表。这可能会更快。
答案 1 :(得分:1)
使用闪电般快速的SqlBulkCopy。您需要一个自定义的IDataReader实现,它可以枚举您的linq查询结果。请查看http://code.msdn.microsoft.com/LinqEntityDataReader以获取更多信息和一些可能合适的IDataReader代码。
答案 2 :(得分:1)
正如同名所说,使用SqlBulkCopy,速度非常快(我发现速度提升超过200倍 - 从1500秒到6秒)。但是,您可以使用DataTable和DataRows类向SQlBulkCopy提供数据(这似乎更容易)。使用SqlBulkCopy这种方式还具有bein .NET 3.0兼容的附加优势(Linq仅在3.5中添加)。
检查http://msdn.microsoft.com/en-us/library/ex21zs8x%28v=VS.100%29.aspx以获取一些示例代码。
答案 3 :(得分:0)
你必须直接使用表达式树,但它是可行的。事实上,它已经为你完成了,你只需要下载源代码:
Batch Updates and Deletes with LINQ to SQL
另一种方法是使用ExecuteMethodCall
的{{1}}和ExecuteCommand
方法来使用存储过程或临时SQL查询。
答案 4 :(得分:0)
即使手动/编程填充数据表(来自任何其他来源的linq),也可以使用SqlDataAdapter进行批量更新。
请记住为数据表中的行手动设置RowState
。请使用dataRow.SetModified()
。