我正在使用WebAPI和Entity Framework 6开发项目。
有一个控制器,其方法是将新实体Task添加到数据库中。在添加任务之前,为它计算一个唯一的名称。部分名称基于数据库中已保存的任务。如果你发出两个并行请求,你可以生成相同的名称,这个问题通过锁定解决。
如果两个WebAPI服务器运行时连接到同一个数据库,如何防止生成相同的名称?
是否可以在数据库级别添加将Task添加到顺序队列的算法?
简化代码:
[HttpPost]
[Route("add")]
public IHttpActionResult AddTask()
{
using (var db = CreateDbContext())
{
Task task = new Task();
lock (lockAdd)
{
DateTime dateTime = DateTime.UtcNow;
string preName = dateTime.ToString("yyMMdd-HHmm-");
var query = db.Tasks.Where(t => t.Name.StartsWith(preName)).Select(t => t.Name);
List<string> tasksNames = query.ToList();
task.Name = preName + (tasksNames.Count + 1).ToString("D4");
db.Tasks.Add(task);
db.SaveChanges();
}
return Ok();
}
}
Сolumn“名称”不能是唯一的。 任务从未删除过。 对于每个新日期(新分钟),计数器必须从1开始。
答案 0 :(得分:1)
您应该使用SEQUENCE在数据库端生成数据。 Docs here。在这种情况下,数据库保证唯一性。 或者使用Guid(UUID) - 它提供唯一键。 Docs here在这种情况下,UUID的概念保证了唯一性
答案 1 :(得分:0)
除了上面的答案,您还可以在C#中生成Guid: https://msdn.microsoft.com/en-us/library/system.guid.newguid%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
唯一性得到保证,因为GUID包含服务器时间和服务器的MAC地址。还有一些较短的解决方案,例如像Snowflake这样的64位UUID生成器。有关C#端口示例,请参阅: https://github.com/mschuler/UniqueIdGenerator或https://github.com/ccollie/snowflake-net/blob/master/Snowflake/IdWorker.cs
(注意:如果你使用单独的Snowflake生成器,你只需要对ID生成器进行锁定,因为在同一毫秒内增量计数器可以保证唯一性,最多可达2 ^ 12个ID / ms /服务器。源已经为此锁定了它。)