簡體   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