2017-07-12 96 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