简体   繁体   English

Controller SQL 数据库中的异步/等待死锁

[英]Controller async/await deadlock in SQL database

I have a controller receiving multiple POST (1000 per minute) from multiple machines and due to that all these data are not inserted in the SQL database and generate some deadlocks.我有一个 controller 从多台机器接收多个 POST(每分钟 1000 个),因此所有这些数据都没有插入 SQL 数据库并产生一些死锁。

How can I lock this method to be used synchronously to insert one after one instead of all at same time?如何锁定此方法以同步使用以一个接一个地插入而不是同时插入所有?

I am able to reproduce the issue with this test controller:我能够通过此测试 controller 重现该问题:

[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();
}

EDIT: This code worked like a charm thanks to Peter answer.编辑:由于彼得的回答,这段代码就像一个魅力。 No deadlock.没有僵局。 Performance was good and no slowness noticed.性能很好,没有注意到任何缓慢。

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();
}

You could use a SemaphoreSlim to limit the access to the database.您可以使用SemaphoreSlim来限制对数据库的访问。 This Semaphore can be awaited asynchously.可以异步等待此信号量。

SemaphoreSlim semaphore = new SemaphoreSlim(1,1);    

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

try - finally is used to make sure the lock is always released, even if eg the database call fails. try - finally用于确保始终释放锁,即使例如数据库调用失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM