【问题标题】:How to check the latest value from a column and generate a new row with that certain value+1?如何检查列中的最新值并生成具有该特定值+1的新行?
【发布时间】:2019-09-05 07:25:13
【问题描述】:

我发现很难弄清楚如何为 API 创建的每个配方自动生成列 ID。此时,如果我想在Recipe表中新建一行,我必须自己插入一个ID,否则它只会被赋值为0。我正在寻找一种方法来检查最新的ID已经存在于数据库,当创建新条目时,其 ID 将为最新 ID + 1。

RecipeController 来自 API

        [Route("v1/recipe")]
    [HttpPost()]
    public IActionResult CreateList([FromBody]Recipe recipe)
    {
        try
        {
            if (recipe == null) throw new ArgumentException("No data specified");
            //if (recipe.Name == null) throw new ArgumentException("No name specified");

            using (var con = _connFactory())
            {
                con.Open();
                con.Execute(@"INSERT INTO dbo.Recipe (Id, Name, RecipeLink, Category1Id ,Category2Id, Category3Id, Category4Id, RecipeById,
                            TotalTime, TotalTimeUnitId, ActiveTime, ActivetimeUnitId, Instructions, SourceKey, RecipeBy, InsertedAtUtc, IsVerified, NumPersons) 
                            VALUES (@id, @name, @recipeLink, @category1Id, @category2Id, @category3Id, @category4Id, @recipeById,
                            @totalTime, @totalTimeUnitId, @activeTime, @activeTimeUnitId, @instructions, @sourceKey, @recipeBy, getutcdate(), @isVerified, @numPersons)",
                            new
                            {
                                recipe.id,
                                recipe.name,
                                recipe.recipeLink,
                                recipe.category1Id,
                                recipe.category2Id,
                                recipe.category3Id,
                                recipe.category4Id,
                                recipe.recipeById,
                                recipe.totalTime,
                                recipe.totalTimeUnitId,
                                recipe.activeTime,
                                recipe.activeTimeUnitId,
                                recipe.instructions,
                                recipe.sourceKey,
                                recipe.recipeBy,
                                recipe.isVerified,
                                recipe.numPersons
                            });
            }
            return Ok(recipe);
        }
        catch (Exception exc)
        {
            return BadRequest();
        }

RecipeController 来自 MVC

        [HttpPost]
    public ActionResult CreateOrEdit(Recipe recipe)
    {
        if (recipe.id == 0)
        {
            HttpResponseMessage response = GlobalVariables.client.PostAsJsonAsync("", recipe).Result;
        }
        else
        {
            HttpResponseMessage response = GlobalVariables.client.PutAsJsonAsync(recipe.id.ToString(), recipe).Result;
        }
        return RedirectToAction("Index");
    }

【问题讨论】:

  • 您应该让数据库来处理创建带有标识列的 ID。
  • “我必须自己插入一个ID,否则它只会被分配到0。” - 为什么?只需设置一个标识列,不要在列列表中包含Id
  • 正如@VDWWD 所说,您可以将 id 列设置为标识并将增量设置为 1。您甚至不需要在插入语句中包含 id 列。数据库会为您处理它
  • 我曾想过让数据库来处理 ID 的创建,但数据库并不是真正属于我的,所以我一直在寻找一种解决方案,而无需实际更改数据库中的某些内容。但是感谢您的提示! @jarlh - SSMS

标签: c# sql asp.net sql-server


【解决方案1】:

如果你不想使用身份字段,你可以像这样获取当前的最高 ID:

SELECT MAX(ID) FROM dbo.Recipe

您可以在单独的查询中执行此操作,也可以将其嵌入到您的插入中:

INSERT INTO dbo.Recipe (Id, Name,...)
VALUES ((SELECT MAX(ID) + 1 FROM dbo.Recipe), @name, …)

如果您使用单独的查询,则应使用事务和表锁,以防两个人同时尝试创建行。

【讨论】:

  • 在插入之前您仍然需要在 MAX(ID) 上加 1
  • 但请确保在选择和插入期间使用 tablelock,否则您可能会多次添加相同的 id。
  • 一个事务不会停止同时读取最大值的 2 个连接。只有一个表锁。
  • 我想这个工具一次只能由一个人使用。无论哪种方式,两个人同时尝试添加一个配方以担心并发事务的可能性非常小。即使在这种情况下,您是否建议我仍然研究表锁定?
  • @Questieme - 对于一个人使用的食谱书,没有必要。但是,如果您这样做是为了学习如何编写业务应用程序,那么您需要了解锁定和并发性。
猜你喜欢
  • 2015-09-04
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-09
  • 2011-03-21
  • 2020-08-01
相关资源
最近更新 更多