让我介绍一些扩展的解决方案。
在这个工作示例中,如您所见,有一个存储过程,它具有输出参数和异步/等待 C# 代码,显示如何接受此输出单个值。
我希望这将有助于理解该方法,并将成为您问题的扩展答案。
C# WinForm
private async void Button1_Click(object sender, EventArgs e)
{
await CleanDevicePositions();
}
public async Task CleanDevicePositions()
{
try
{
var endDate = DateTime.Now.AddDays(-120).ToString("yyyyMMdd");
using (var db = new TechServiceEntities())
{
db.Database.CommandTimeout = 18000;
object[] parameters = {
new SqlParameter("@MaxToDeleteInp", 1000),
new SqlParameter("@BatchSizeInp", 100),
new SqlParameter("@ToEndDateInp", endDate),
new SqlParameter
{
ParameterName = "@Records",
SqlDbType = SqlDbType.Int,
Value = -1,
Direction = ParameterDirection.Output
}
};
// For result description have a look at https://docs.microsoft.com/en-us/sql/relational-databases/stored-procedures/return-data-from-a-stored-procedure?view=sql-server-ver15
var result = await db.Database.
ExecuteSqlCommandAsync($"EXEC dbo.DeleteOldDevicePositions @MaxToDeleteInp, @BatchSizeInp, @ToEndDateInp, @Records OUTPUT", parameters)
.ConfigureAwait(false); ;
var retValue = (parameters[3] as SqlParameter).Value;
BeginInvokeLambda(listBox1, () => { listBox1.Items.Add(retValue); });
BeginInvokeLambda(listBox1, () => { listBox1.Items.Add(result); });
}
}
catch (SqlException ex)
{
Debug.WriteLine(ex);
BeginInvokeLambda(listBox1, () => { listBox1.Items.Add(ex.ToString()); });
BeginInvokeLambda(listBox1, () => { listBox1.Items.Add(ex.Message); });
}
catch (Exception ex)
{
Debug.WriteLine(ex);
BeginInvokeLambda(listBox1, () => { listBox1.Items.Add(ex.ToString()); });
BeginInvokeLambda(listBox1, () => { listBox1.Items.Add(ex.Message); });
}
}
private static IAsyncResult BeginInvokeLambda(Control control, Action action)
{
if (!control.IsDisposed)
{
return control.BeginInvoke(action, null);
}
return null;
}
TSQL
这个 SP 只是按照定义的批量大小删除一些记录。
ALTER PROCEDURE [dbo].[DeleteOldDevicePositions]
@MaxToDeleteInp int = 1000, -- Max amount of records to delete
@BatchSizeInp int = 100, -- it is
@ToEndDateInp datetime, -- Delete until this datetime
@Records int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @MaxToDelete int , @BatchSize int , @ToEndDate datetime;
SET @MaxToDelete = @MaxToDeleteInp;
SET @BatchSize = @BatchSizeInp;
SET @ToEndDate = @ToEndDateInp;
DECLARE @TransactionInterval tinyint = 5, @FactDeleted int = 0;
DECLARE @counter int = 1;
DECLARE @s datetime, @e datetime, @r int = 1;
SELECT @s = MIN(AtTime) FROM dbo.DevicePositions;
BEGIN TRANSACTION;
WHILE (@r > 0)
BEGIN
IF @r % @TransactionInterval = 1
BEGIN
COMMIT TRANSACTION;
BEGIN TRANSACTION;
END
DELETE TOP (@BatchSize) FROM DevicePositions WHERE AtTime >= @s AND AtTime <= @ToEndDate;
SET @FactDeleted = @FactDeleted +@BatchSize;
SET @r = @@ROWCOUNT;
SET @counter = @counter + 1;
IF @FactDeleted >= @MaxToDelete
BREAK;
END
IF @@TRANCOUNT > 0
BEGIN
COMMIT TRANSACTION;
IF @counter % 10 = 0 -- or maybe 100 or 1000
BEGIN
CHECKPOINT;
END
END
SELECT @Records = A.Records FROM (
SELECT OBJECT_NAME(object_id) as ID, SUM(row_count) AS Records FROM sys.dm_db_partition_stats WHERE
object_id = OBJECT_ID('DevicePositions') AND index_id < 2
GROUP BY OBJECT_NAME(object_id) ) A
RETURN @Records;
END
应用
这里可以看到删除后的记录数。