繁体   English   中英

Linq to SQL - 更新批处理

[英]Linq to SQL - Update Batch

我有以下内联SQL:

    internal void UpdateWorkflowProcessingByNullToken(Guid processingToken, int numberToProcess)
    {
        string sql = string.Format(CultureInfo.InvariantCulture,
            "UPDATE TOP ({0}) Master.WorkflowEventProcessing " +
            "SET ProcessingToken = '{1}' " +
            "WHERE ProcessingToken IS NULL",
            numberToProcess, processingToken);

        this.Database.ExecuteCommand(sql);
    }

内联SQL用于提高性能。 据我所知,L2S会为我需要更新的每一行创建一个SQL语句。 这花了太长时间。 请注意,这是几年前的事了。

现在我有一个DBA告诉我这个:

  • 此查询似乎是最频繁阻止或被阻止的查询之一。
  • 从数据库的角度来看,这不是优化的,因为需要为每次执行生成执行计划。
  • 根据数据,这个简单的查询使用超过1GB的计划缓存(超过25000个类似的执行计划副本),而如果只存储1个副本,它实际上只能使用少于50KB的内存。
  • 我建议使用唯一标识符作为参数创建存储过程。 按照设计,存储过程(绕过编译阶段)应该比ad hoc查询运行得更快。

作为开发人员,我们一直不愿意使用存储过程。 我们喜欢在C#数据层中拥有所有数据代码。 我被困在这里吗? 我需要使用存储过程吗? 或者有没有办法用L2S进行大规模更新?

我记得读过有关编译L2S查询的内容。 我也可以调查一下......

您可以使用参数化SQL命令来执行。 这将生成可重用的查询执行计划,该计划在最初创建和缓存之后将与存储过程一样高效。 每次执行都只需提供新参数。

更多细节

给出以下代码更新演示数据库和名为“Foo”的表

///////////////////////////////////////////////////////////
// just setup for the context for demo purposes, you would
// reference this.Database in place of creating context.
SqlConnection connection = new SqlConnection("Data Source = .; Initial Catalog = MyDb; Integrated Security = SSPI;");
var dataContext = new System.Data.Linq.DataContext(connection);
///////////////////////////////////////////////////////////

string updateQuery = "UPDATE TOP (@p1) dbo.Foo " +
"SET Data = @p2 " +
"WHERE Data IS NULL";

dataContext.Connection.Open();

var command = dataContext.Connection.CreateCommand();
command.CommandText = updateQuery;
command.CommandType = System.Data.CommandType.Text;

var param1 = new SqlParameter("@p1", System.Data.SqlDbType.Int);   
param1.Value = 3;
command.Parameters.Add(param1);

var param2 = new SqlParameter("@p2", System.Data.SqlDbType.Int);
param2.Value = 1;
command.Parameters.Add(param2);
command.Prepare();
command.ExecuteNonQuery();

param2.Value = 5;
command.ExecuteNonQuery();

从分析器输出中,您可以看到它调用sp_prepexec

declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@p1 int,@p2 int',N'UPDATE TOP (@p1) dbo.Foo SET Data = @p2 WHERE Data IS NULL',@p1=3,@p2=1
select @p1

并执行传递参数3和1的语句,然后当param2.Value设置为5并再次执行命令时,分析器显示它重用准备好的命令(因此不会重新编译或生成新的执行计划)

exec sp_execute 1,@p1=3,@p2=5

这就是分析器输出的样子,仅供参考... 在此输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM