.Net核心异步方法线程安全

时间:2021-06-30 04:25:09

标签: c# .net-core

我正在尝试在 .Net Core 3.1 中创建示例 Web Api 项目,这有助于销售在线剧院门票。所以我添加了控制器方法,它返回当前客户端的最后一个票号:

namespace MyTestWebAPI1.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class TicketController : Controller
    {
        private ILogger<TicketController> _logger;
        private DataContext _context;
        public TicketController(ILogger<TicketController> logger, DataContext context)
        {
            _logger = logger;
            _context = context;
        }

        [HttpGet]
        public async Task<string> GetTicketNumber()
        {
            var ticketNumber = string.Empty;
            using (var cmd = _context.Database.GetDbConnection().CreateCommand())
            {
                bool wasOpen = cmd.Connection.State == ConnectionState.Open;
                if (!wasOpen) cmd.Connection.Open();
                try
                {
                    //Calling database scalar function:
                    cmd.CommandText = $"select Get_Next_Ticket_Number() from dual";
                    var scalarResult = cmd.ExecuteScalar();
                    ticketNumber == DBNull.Value ? string.Empty : (string)scalarResult;                    
                }
                finally
                {
                    if (!wasOpen) cmd.Connection.Close();
                }
            }
          //Here has other code segment which linked to save client data to database, 
          //for this i simpley replacing it with Task.Delay() for sample ))
            await Task.Delay(20000); 
            return ticketNumber;
        }
    }
}

我怎样才能做到这个方法线程安全,那些。它没有向多个客户端返回一张票数据

2 个答案:

答案 0 :(得分:1)

你的代码几乎就是“买一只狗然后自己吠叫”

  • 使数据库在插入时生成票号(自动递增编号或 Guid)
  • 插入一条记录(创建一个没有票号的新票务实体)并保存
  • EF 将检索数据库生成的值并将它们放入实体中(可能通过执行 INSERT INTO .. RETURNING .. 但我们并不真正关心;这是 EF 提供者的问题,而不是我们的问题)
  • 使用更新后的详细信息生成二维码
  • 所有这些都是作为同一个控制器方法的一部分发生的;用户已登录,您知道他们是谁,您插入与他们的帐户相关联的票证,以便在您发现他们是谁(他们登录)后随时可以检索它

所有这些“获取连接,运行一个 sql 找出先前插入的记录,互斥锁并锁定它以便一次只能运行一个 sql 等等等等”只是破解;如果你要进入那个兔子洞,你最好不要使用 EF。

这一切都已经为您处理好了,线程管理和并发请求也是如此,如果您按照预期使用的方式进行处理;你越是颠覆它,你就越会在 hack 之后堆积如山,让生活变得更加艰苦

答案 1 :(得分:-1)

设置索引 od 数据库列并使它们唯一。如果两个客户端同时调用GetTicketNumber,你会得到异常。

相关问题