带有标识列的SQL Server中的重复记录

时间:2014-04-15 20:11:18

标签: c# sql-server-2008 identity identity-column

我有一个ASP.Net Web窗体应用程序,它使用SqlCommand并使用ExecuteNonQuery方法将新记录(请求)插入到SQL Server表中。该表有一个主键(int id),为Identity Specification = Yes,Identity Increment 1,Identity Seed 1设置。该应用程序已经工作多年。大约一个月前,数据库从物理服务器移动到虚拟服务器,没有任何明显的问题。该数据库在SQL Server 10.50.1617.0上运行。

最近,用户报告创建了大约90个请求但无法找到它们。当我检查请求表时,我只能在过去几天找到为她创建的一个请求。请求表上的最高ID为5404.作为实验,我让她创建了一个新请求。我期待它创建一个5405的新ID,但它实际上创建了一个2975的id。我让她创建了另一个请求,它在id 2975上覆盖了第一个请求和另一个请求。我创建了一个测试请求,它创建了一个在id 5405.什么可能导致这个?

以下是插入的c#:

        string sql = "insert into requests (end_user_email) values (@email)";
        SqlConnection cn = new SqlConnection(_cnString);

        SqlCommand cmdIns = new SqlCommand(sql, cn);
        cmdIns.Parameters.Add("@email", SqlDbType.NVarChar);
        cmdIns.Parameters["@email"].Value = email;

        cmdIns.Connection.Open();
        cmdIns.ExecuteNonQuery();

2 个答案:

答案 0 :(得分:4)

您的表名不符合架构(例如dbo.requests)。我怀疑你的数据库中有两个不同的表,名称相同。一个由dbo架构拥有;另一个是您的默认架构。

SQL Server名称解析对非限定引用的工作原理如下:

  1. 在当前连接凭据定义的默认架构下探测指定名称的对象的命名空间。如果找到一个,该对象将解析引用。否则...

  2. dbo模式下探测指定名称的对象的名称空间。如果找到一个,该对象将解析引用。否则...

  3. 如果对象是名称以sp_开头的存储过程,则对master数据库执行命名空间的进一步探测,如上面的步骤#1和#2所示。

  4. 最后,如果未解析引用,则名称解析将失败。

  5. 您的用户正在使用包含一个默认架构的凭据进行连接,并解析为该架构或requests所拥有的名为dbo的表。

    另一方面,您正在使用其他默认架构的凭据,并找到具有相同名称的不同的表,这些表由默认架构或dbo拥有。

    应该总是架构限定对象引用,原因有两个:

    • 性能。命名空间的两个探测器用于查找您可能需要的dbo拥有的对象,这会使您在性能方面付出代价。
    • 此外,涉及非限定引用的执行计划可能不会被缓存,从而导致额外的重新编译。

    • 最后,你或其他人会在某个时候射击自己。通常,它将由一方执行存储过程的一个版本而另一方执行不同的版本。欢闹随之而来 - “它适用于我的机器!”。更好的是当不同的人遇到同一个表的不同版本时,收到关于缺失列的看似随机的错误。

    <强>无论其...

    identity列的{ - 1}}属性值并非闻所未闻:identity属性因各种原因与数据不同步。

    因此,如果您排除了同一个表的两种不同风格,那么您需要让DBA针对该表运行DBCC CHECKIDENT,以使该表的identity计数器恢复同步表中的高水位标记。

    • DBCC CHECKIDENT({table-name},noreseed)

      报告表格的identity计数器和表格中当前的高水位线的当前值。

    • DBCC CHECKIDENT({table-name},reseed)

      重新设定identity计数器以匹配表格中的高水位线。

答案 1 :(得分:0)

也有可能客户端从单台服务器移至沙盒或云,而无法更改应用程序的web.config。

<!--
        If you are deploying to a cloud environment that has multiple web server instances,
        you should change session state mode from "InProc" to "Custom". In addition,
        change the connection string named "DefaultConnection" to connect to an instance
        of SQL Server (including SQL Azure and SQL  Compact) instead of to SQL Server Express.
  -->
<sessionState mode="InProc" customProvider="DefaultSessionProvider">

在这种情况下,移动到nvarchar(128)或GUID并使用newID()为其他记录分配唯一ID也可能会有所帮助。