2017-07-12 63 views
1

我有一个控制器从多台机器接收多个POST(每分钟1000),并且由于所有这些数据都没有插入到SQL数据库中并产生了一些死锁。控制器异步/等待SQL数据库中的死锁

如何锁定此方法以便同时使用,而不是同时插入一个而不是全部?

我能够重现该问题与此测试控制器:

[HttpPost] 
public async Task<ActionResult> Create([Bind(Include = "Value1,Value2,Id")] Test test) 
{ 
    if (ModelState.IsValid) 
    { 
     db.Tests.Add(test); 
     await db.SaveChangesAsync(); 
    } 

    return new EmptyResult(); 
} 

编辑:此代码工作一个魅力感谢Peter答案等。没有死锁。表现很好,没有发现缓慢。

private SemaphoreSlim _semaphore = new SemaphoreSlim(1); 

[HttpPost] 
public async Task<ActionResult> Create([Bind(Include = "Value1,Value2,Id")] Test test) 
{ 
    await _semaphore.WaitAsync(); 

    if (ModelState.IsValid) 
    { 
     db.Tests.Add(test); 
     await db.SaveChangesAsync().ConfigureAwait(false); 
    } 

    _semaphore.Release(); 
    db.Dispose(); 

    return new EmptyResult(); 
} 
+0

为什么在等待任务时不使用'ConfigureAwait(false)'? –

+2

@PeterBruins什么'ConfigureAwait'与此有什么关系?另外op正在讨论SQL Server中的死锁,而不是.NET代码。而'ConfigureAwait'也不是解决所有问题的方法。 –

+0

你的意思是等待db.SaveChangesAsync()。ConfigureAwait(false)?我会试一试,让你知道。 – expirat001

回答

1

您可以使用SemaphoreSlim来限制对数据库的访问。这个信号量可以被异步地等待。

SemaphoreSlim semaphore = new SemaphoreSlim(1,1);  

public async Task<ActionResult> Create([Bind(Include = "Value1,Value2,Id")] Test test) 
{ 
    await semaphore.WaitAsync().ConfigureAwait(false); 
    if (ModelState.IsValid) 
    { 
     db.AuditTests.Add(test); 
     await db.SaveChangesAsync().ConfigureAwait(false); 
    } 
    semaphore.release(); 
    return new EmptyResult(); 
} 
+0

谢谢彼得。将有可能告诉我如何在我的代码中实现SemaphoreSlim? – expirat001

+0

我现在尝试,我会更新结果。 – expirat001

+0

它像一个魅力,20 000个帖子和数据库中的20 000条记录。 – expirat001