我有一个使用.net 6
的后端系统,我通过手动自动增加来生成用户名。
我们的用户名是基于公司和角色的。因此,如果我们假设公司为a1
和a2
,角色为employee
和manager
,则{company}-{role}{number}
中的id将为a1-e0001
、a2-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
// ...
// ...
问题是,当在短时间内多次调用此方法时(这是一种实际情况),它将发生冲突,并为两个请求给予相同的用户名,因为第二个请求将在第一个请求插入新用户之前开始运行,因此第二个请求也将获得相同的用户名。
什么是避免这种冲突的好方法呢?我曾想过阻止对这个问题的其他调用,直到前一个调用解决,但找不到如何做到这一点的方法。
1条答案
按热度按时间oknwwptz1#
阻止是可行的,但在你的情况下会大大降低性能。我的解决方案是使用某种数据库级可管理的标识种子。例如,在MSSQL中,你可以创建一个表,在插入时为你生成ID,如
在插入时,您将拥有线程安全ID,您可以稍后通过简单的concat
$"u-{ID}"
将其呈现给您的用户。这样,您就不必担心并发访问,而且您的登录比使用guid更好。我确信您不必拘泥于MSSQL,您的数据库引擎也可以做到这一点。