【问题标题】:Delete in the middle row where the id using auto generate in C#在 C# 中使用自动生成的 id 删除中间行
【发布时间】:2014-03-08 21:53:24
【问题描述】:

我在 sql server 2005 中创建了一个数据库,并使用 count all rows 表创建了一个带有自动生成 id 字段的表。

我还在 c# 桌面应用程序中开发了一个项目。

我有一个问题,如果我在数据库中删除 1 行表,其中 id 是通过编码 c# 自动生成的,我如何设置自动生成 id 就像之前删除的 id 一样? 因为在我删除字段的同时,所有行的计数都减少了,我的计数增加了。

所以,我的自动生成 id 是错误的,因为 id 冲突。

这是我的自动生成 ID

public string generateIdActivity()
{
    string activity = "";
    int jml = myActivity.getCountActivity() + 1;
    if (myActivity.getCountActivity() < 10)
    {
        activity = "ACT0000" + jml;
    }
    if (myActivity.getCountActivity() < 100 && myActivity.getCountActivity() > 9)
    {
        activity = "ACT000" + jml;
    }
    if (myActivity.getCountActivity() < 1000 && myActivity.getCountActivity() > 99)
    {
        activity = "ACT00" + jml;
    }
    if (myActivity.getCountActivity() < 10000 && myActivity.getCountActivity() > 999)
    {
        activity = "ACT0" + jml;
    }
    if (myActivity.getCountActivity() < 100000 && myActivity.getCountActivity() > 9999)
    {
        activity = "ACT" + jml;
    }
    return activity;
}

【问题讨论】:

  • 我知道评论与这里提出的问题无关。但是这段代码可以即兴创作。您多次调用函数 myActivity.getCountActivity() 。这是不必要的开销。您可以将值保存到变量并使用它,或者您可以使用变量(jml - 1)..这将即兴代码..它只是建议..

标签: c# sql winforms sql-server-2005


【解决方案1】:

你没有。
我建议让 SQL 服务器为您分配 id(使用 identity property)。

【讨论】:

  • 坏主意。永远不要让身份属性生成业务级别的编号方案。可能还有其他要求 - 例如没有孔,身份不能保证(但发票号码,例如法律要求)。您需要一个自定义序列。而 sql 2005 意味着必须编程。
  • @TomTom - 谁说这是在生成“业务级”编号方案?恕我直言,在发票号码之类的业务环境中使用主键是个坏主意,而且依赖连续的键序列更糟糕。
  • @StephenByrne 事实上,他的活动 ID 不是纯数字,而是以前缀开头。并且使用业务键作为主键很棒——有一整套思想在谈论 sql 中的自然键。不是我喜欢它......但是谁说主键。唯一索引也有同样的问题。请仔细考虑你的陈述。
  • @TomTom - 很公平,但这是您对他身份的目的的假设。而且我不想将其拖入自然与替代关键的辩论中,我只想说在我看来并基于个人经验,这是一个坏主意。但如果它对你有用,那就太好了!
【解决方案2】:

具有自动生成 id 字段的表

给你。标识字段不计算行数,在元数据表中有一个单独的计数器。

因此,在插入 4 之后,您将得到 5 - 无论 4 或任何其他行是否仍然存在或已被删除。

但是:您没有自动生成的 Id 字段。

你的设计很糟糕。

问题粗暴地说: * 不计算,使用最大值 * 但是 - 你如何同时处理多个用户/线程的多个插入?

通常,您要查找的是应在数据库中实现并要求下一个数字的序列。 Sql server 2012 中的琐碎 - 使用(新)序列。对于 2005,您应该将自己的最后一个值放入单独表中的某个字段中。

http://www.sqlteam.com/article/custom-auto-generated-sequences-with-sql-server

描述了自定义序列的各种方法。

【讨论】:

    【解决方案3】:

    您不应该使用这种方法来生成密钥,因为正如您自己已经看到的那样,它会导致各种问题。

    还请考虑如果您的应用程序的两个或多个实例尝试同时插入记录会发生什么 - 它们很可能最终都在表中获得相同的记录数,并且都尝试发送相同的 ID。

    如果您想要自动生成的密钥,最简单的做法是使用标识列:

    CREATE TABLE MyTable
    (
        ID int identity primary key,
        SomeData nvarchar(255)
    )
    

    现在当你想插入到上面的表格中时,你只需要使用 INSERT INTO MyTable(SomeData) Values ('hello world') 和 ID 列将自动分配,永远不会发生冲突。

    您可以使用SELECT SCOPE_IDENTITY()从特定连接中检索最后生成的身份,这样您就可以知道您刚刚插入的记录的ID。

    更新:关于您正在使用的密钥的小注释。

    我建议不要使用看起来像 'ACT00001' 或类似的主键,因为虽然现在它是有道理的(活动性,非常聪明),你实际上是在把自己画到一个角落 - 如果企业在 6 个月后决定“活动”真的应该被称为“任务”,那么你就会被一堆看起来很奇怪的标识符所困,你不能轻易改变。

    现在最好坚持使用数字标识符,您始终可以格式化它以在演示代码中显示“ACT00001”等。

    身份列在恕我直言,我不明白为什么不应该在你的情况下使用它们,或者你也可以使用sequence编辑:我注意到你正在使用 SQL Server 2005 所以这实际上是不可能的)

    【讨论】:

    • 有趣的是,他从不说主键。我的数据库有一个模式,在大多数名为 Code 的表中都有一个唯一的 id 字段,并且在某些表中必须遵循一些自动生成的机制(例如发票编号)。 Id 不会自动暗示主键 - 唯一索引会触发相同的行为。
    • @TomTom 是的,我想我也为假设感到内疚:)
    猜你喜欢
    • 2012-04-24
    • 2014-08-26
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 2018-08-27
    • 1970-01-01
    相关资源
    最近更新 更多