如何使并行数据库更改顺序?

时间:2017-11-22 16:52:06

标签: c# postgresql asp.net-web-api entity-framework-6

我正在使用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开始。

2 个答案:

答案 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/UniqueIdGeneratorhttps://github.com/ccollie/snowflake-net/blob/master/Snowflake/IdWorker.cs

(注意:如果你使用单独的Snowflake生成器,你只需要对ID生成器进行锁定,因为在同一毫秒内增量计数器可以保证唯一性,最多可达2 ^ 12个ID / ms /服务器。源已经为此锁定了它。)