這個指令還是會把所有的資料 Select 出來,再更新
原指令:
UPDATE Job Set En_Status = 200 Where En_Status = 100 and LastTouchAt < '2023-05-06 12:34:56'
其中 '2023-05-06 12:34:56' 是 DateTime.Now.AddMinutes(-2) 的結果(Web Server 端的時間扣 2 分鐘)
但,若是改使用 UpdateFromQueryAsync 如下:
var c = await Ds.NewContext.GvContext.Jobs.Where(j => j.En_Status == Cst.Job.Status.Running && j.LastTouchAt < DateTime.Now.AddMinutes(-2))
.UpdateFromQueryAsync(j => new Ds.Gv.Job { En_Status = Cst.Job.Status.ReStarting });
產生的 SQL 如下:
UPDATE A
SET A.[En_Status] = @zzz_BatchUpdate_0
FROM [Job] AS A
INNER JOIN ( SELECT [j].[Id], [j].[CancelledAt], [j].[CancelledBy], [j].[En_Status], [j].[EndAt], [j].[Exception], [j].[Filename], [j].[InformationJson], [j].[InitAt], [j].[Is_CheckOnly], [j].[LastTouchAt], [j].[LastTouchMessage], [j].[LoopStartAt], [j].[Name], [j].[ScheduleId], [j].[TotalTouch], [j].[TouchCount]
FROM [Job] AS [j]
WHERE [j].[En_Status] = 100 AND [j].[LastTouchAt] < DATEADD(minute, CAST(-2.0E0 AS int), GETDATE())
) AS B ON A.[Id] = B.[Id]
有兩個要注意的地方:
1. 它會先 Select 全欄位,再做更新
2. 它的時間是 DB Server 的現在時間。不是 Web Server 端的時間。
順便記錄一下。若是要執行 Update xx Ser cc = cc + 1 Where ...
EF 可寫為:
var c = await Ds.NewContext.GvContext.Jobs.Where(j => j.En_Status == Cst.Job.Status.Running && j.LastTouchAt < DateTime.Now.AddMinutes(-2))
.UpdateFromQueryAsync(j => new Ds.Gv.Job { TotalTouch = j.TotalTouch + 1 });
轉換的 SQL 為:
UPDATE A
SET A.[TotalTouch] = B.[TotalTouch] + 1
FROM [Job] AS A
INNER JOIN ( SELECT [j].[Id], [j].[CancelledAt], [j].[CancelledBy], [j].[En_Status], [j].[EndAt], [j].[Exception], [j].[Filename], [j].[InformationJson], [j].[InitAt], [j].[Is_CheckOnly], [j].[LastTouchAt], [j].[LastTouchMessage], [j].[LoopStartAt], [j].[Name], [j].[ScheduleId], [j].[TotalTouch], [j].[TouchCount]
FROM [Job] AS [j]
WHERE [j].[En_Status] = 100 AND [j].[LastTouchAt] < DATEADD(minute, CAST(-2.0E0 AS int), GETDATE())
) AS B ON A.[Id] = B.[Id]
Bike, 2023/4/29 下午 08:44:31
在新增 .Net 7 專案時。不用特別指定 app.UseRouting() 就可以使用 attribute routing.
但會遇到一個問題:
原來應該出靜態檔案的 Request 會被符合 Routing Rule 的 Action 攔截。
解決的方法是 :
在 UseStaticFiles 之後手動再加上 app.UseRouting(), 範例如下:
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
const int durationInSeconds = 60 * 60 * 24 * 365; //一年
ctx.Context.Response.Headers[HeaderNames.CacheControl] =
"public,max-age=" + durationInSeconds;
}
});
app.UseRouting();
Bike, 2023/3/2 下午 03:32:41