在 .NET Core 中取消存储过程
Cancel stored procedure in .NET Core
我有一个 table:
CREATE TABLE [dbo].[Semaphores](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nchar](10) NULL
) ON [PRIMARY]
我有一个存储过程:
ALTER PROCEDURE [dbo].[SpCreateLock] @Name nvarchar(50)
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRANSACTION
INSERT INTO Semaphores VALUES (@Name)
Waitfor delay '00:00:10'
COMMIT TRANSACTION
END
我有一个简单的控制台 .NET Core 应用程序:
class Program
{
private static readonly DbContextOptions DbContextOptions;
static Program()
{
var connectionString = "server=(localdb)\ProjectsV13; database=test; trusted_connection=true";
DbContextOptions = new DbContextOptionsBuilder()
.UseSqlServer(connectionString)
.Options;
}
static async Task Main(string[] args)
{
await TryGetLock();
Console.ReadKey();
}
private async static Task TryGetLock()
{
using (var context = new DatabaseContext(DbContextOptions))
using (var cancellationTokenSource = new CancellationTokenSource())
{
var cancellationToken = cancellationTokenSource.Token;
cancellationTokenSource.CancelAfter(5000);
cancellationToken.ThrowIfCancellationRequested();
try
{
context.Database.OpenConnection();
var result = await context.Database.ExecuteSqlCommandAsync("exec SpCreateLock qwerty", cancellationToken);
}
catch (OperationCanceledException e)
{
}
}
}
}
我正在调用 Main 中的 TryGetLock 方法。应用程序启动后,我转到 ssms 并调用一个简单的 select * from Semaphores
- 它被暂停(正在执行查询),因为 .NET Core 应用程序正在使用 table(可序列化隔离级别)。在我的应用程序中的查询被取消后,我希望 ssms 中的查询完成 - 但事实并非如此,它显然陷入了僵局。它仅在我关闭我的 .NET Core 应用程序时完成。我尝试关闭、处理数据库连接,但它没有改变任何东西。
我在这里错过了什么?
我最终摆脱了 sql 过程中的事务创建并将其放入 c# 代码中。
sql:
ALTER PROCEDURE [dbo].[SpCreateLock] @Name nvarchar(50)
AS
BEGIN
INSERT INTO Semaphores VALUES (@Name)
Waitfor delay '00:00:10'
END
c#:
class Program
{
private static readonly DbContextOptions DbContextOptions;
public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider((_, __) => true, true) });
static Program()
{
var connectionString = "server=(localdb)\ProjectsV13; database=test; trusted_connection=true";
DbContextOptions = new DbContextOptionsBuilder()
.UseSqlServer(connectionString)
.EnableSensitiveDataLogging()
.UseLoggerFactory(MyLoggerFactory)
.Options;
}
static async Task Main(string[] args)
{
await TryGetLock();
Console.ReadKey();
}
private async static Task TryGetLock()
{
IDbContextTransaction transaction = null;
var context = new DatabaseContext(DbContextOptions);
var cancellationTokenSource = new CancellationTokenSource();
try
{
var cancellationToken = cancellationTokenSource.Token;
cancellationTokenSource.CancelAfter(5000);
context.Database.OpenConnection();
transaction = context.Database.BeginTransaction(IsolationLevel.Serializable);
var result = await context.Database.ExecuteSqlCommandAsync("exec SpCreateLock qwerty", cancellationToken);
context.Database.CommitTransaction();
}
catch (Exception e)
{
context.Database.RollbackTransaction();
}
finally
{
cancellationTokenSource?.Dispose();
transaction?.Dispose();
context?.Dispose();
}
}
}
我有一个 table:
CREATE TABLE [dbo].[Semaphores](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nchar](10) NULL
) ON [PRIMARY]
我有一个存储过程:
ALTER PROCEDURE [dbo].[SpCreateLock] @Name nvarchar(50)
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRANSACTION
INSERT INTO Semaphores VALUES (@Name)
Waitfor delay '00:00:10'
COMMIT TRANSACTION
END
我有一个简单的控制台 .NET Core 应用程序:
class Program
{
private static readonly DbContextOptions DbContextOptions;
static Program()
{
var connectionString = "server=(localdb)\ProjectsV13; database=test; trusted_connection=true";
DbContextOptions = new DbContextOptionsBuilder()
.UseSqlServer(connectionString)
.Options;
}
static async Task Main(string[] args)
{
await TryGetLock();
Console.ReadKey();
}
private async static Task TryGetLock()
{
using (var context = new DatabaseContext(DbContextOptions))
using (var cancellationTokenSource = new CancellationTokenSource())
{
var cancellationToken = cancellationTokenSource.Token;
cancellationTokenSource.CancelAfter(5000);
cancellationToken.ThrowIfCancellationRequested();
try
{
context.Database.OpenConnection();
var result = await context.Database.ExecuteSqlCommandAsync("exec SpCreateLock qwerty", cancellationToken);
}
catch (OperationCanceledException e)
{
}
}
}
}
我正在调用 Main 中的 TryGetLock 方法。应用程序启动后,我转到 ssms 并调用一个简单的 select * from Semaphores
- 它被暂停(正在执行查询),因为 .NET Core 应用程序正在使用 table(可序列化隔离级别)。在我的应用程序中的查询被取消后,我希望 ssms 中的查询完成 - 但事实并非如此,它显然陷入了僵局。它仅在我关闭我的 .NET Core 应用程序时完成。我尝试关闭、处理数据库连接,但它没有改变任何东西。
我在这里错过了什么?
我最终摆脱了 sql 过程中的事务创建并将其放入 c# 代码中。
sql:
ALTER PROCEDURE [dbo].[SpCreateLock] @Name nvarchar(50)
AS
BEGIN
INSERT INTO Semaphores VALUES (@Name)
Waitfor delay '00:00:10'
END
c#:
class Program
{
private static readonly DbContextOptions DbContextOptions;
public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider((_, __) => true, true) });
static Program()
{
var connectionString = "server=(localdb)\ProjectsV13; database=test; trusted_connection=true";
DbContextOptions = new DbContextOptionsBuilder()
.UseSqlServer(connectionString)
.EnableSensitiveDataLogging()
.UseLoggerFactory(MyLoggerFactory)
.Options;
}
static async Task Main(string[] args)
{
await TryGetLock();
Console.ReadKey();
}
private async static Task TryGetLock()
{
IDbContextTransaction transaction = null;
var context = new DatabaseContext(DbContextOptions);
var cancellationTokenSource = new CancellationTokenSource();
try
{
var cancellationToken = cancellationTokenSource.Token;
cancellationTokenSource.CancelAfter(5000);
context.Database.OpenConnection();
transaction = context.Database.BeginTransaction(IsolationLevel.Serializable);
var result = await context.Database.ExecuteSqlCommandAsync("exec SpCreateLock qwerty", cancellationToken);
context.Database.CommitTransaction();
}
catch (Exception e)
{
context.Database.RollbackTransaction();
}
finally
{
cancellationTokenSource?.Dispose();
transaction?.Dispose();
context?.Dispose();
}
}
}