.net C#:不要让动作一次执行一次以上

yquaqz18  于 2022-11-26  发布在  .NET
关注(0)|答案(1)|浏览(148)

我有一个使用.net 6的后端系统,我通过手动自动增加来生成用户名。
我们的用户名是基于公司和角色的。因此,如果我们假设公司为a1a2,角色为employeemanager,则{company}-{role}{number}中的id将为a1-e0001a2-m0010 ...
代码如下:

[HttpPost]
[Route("create")]
public async Task<BaseDto?> Create([FromBody] reqDto)
{
    var lastUser = usersRepository
    .Where(e => e.Company == reqDto.Company && e.Role == reqDto.Role)
    .SortByUserName().LastOrDefault();

    var lastUserName = lastUser?.UserName;
    var lastUserNameInt = int.Parse(lastUserName.Split('-')[1]);
    var newUserName = e.Company + "-" + e.Role + (lastUserNameInt + 1);

    // create the user
    // ...
    // ...

问题是,当在短时间内多次调用此方法时(这是一种实际情况),它将发生冲突,并为两个请求给予相同的用户名,因为第二个请求将在第一个请求插入新用户之前开始运行,因此第二个请求也将获得相同的用户名。
什么是避免这种冲突的好方法呢?我曾想过阻止对这个问题的其他调用,直到前一个调用解决,但找不到如何做到这一点的方法。

oknwwptz

oknwwptz1#

阻止是可行的,但在你的情况下会大大降低性能。我的解决方案是使用某种数据库级可管理的标识种子。例如,在MSSQL中,你可以创建一个表,在插入时为你生成ID,如

CREATE TABLE [dbo].[User](
    [Id] [int] IDENTITY(1,1) NOT NULL
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [Id] ASC )

在插入时,您将拥有线程安全ID,您可以稍后通过简单的concat $"u-{ID}"将其呈现给您的用户。这样,您就不必担心并发访问,而且您的登录比使用guid更好。我确信您不必拘泥于MSSQL,您的数据库引擎也可以做到这一点。

相关问题