Дублирование записей в SQL Server со столбцом идентификации

У меня есть приложение ASP.Net Web Forms, которое вставляет новые записи (запросы) в таблицу SQL Server с помощью SqlCommand и метода ExecuteNonQuery. Таблица имеет один первичный ключ (int id), для которого задано значение «Спецификация удостоверения» = «Да», приращение удостоверения 1, начальное значение удостоверения 1. Приложение работает уже много лет. Около месяца назад база данных была перемещена с физического сервера на виртуальный сервер без каких-либо явных проблем. База данных работает на SQL Server 10.50.1617.0.

Совсем недавно пользователь сообщил, что создал около 90 запросов, но не смог их найти. Когда я изучил таблицу запросов, я смог найти только один запрос, созданный для нее за последние несколько дней. Самый высокий идентификатор в таблице запросов был 5404. В качестве эксперимента я попросил ее создать новый запрос. Я ожидал, что он создаст новый идентификатор 5405, но на самом деле он создал идентификатор 2975. Я попросил ее создать еще один запрос, и он перезаписал первый запрос другим с идентификатором 2975. Я создал тестовый запрос, и он создал один на id 5405. Что может быть причиной этого?

Вот С# для вставки:

        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();

person Kevin Clary    schedule 15.04.2014    source источник
comment
То, что вы описываете, не происходит с кодом, который вы показали здесь. Я бы предположил, что у вас есть триггер, который ищет вставки и вместо этого выполняет обновления в таблице.   -  person crthompson    schedule 16.04.2014
comment
Он действительно воссоздал 2975 или просто обновил его? А как перенесли? Похоже, проблема со свойствами Identity, возможно, или она, возможно, выполняет обновление, а не вставку. Это происходит для всех запросов или только для этих?   -  person jensendp    schedule 16.04.2014
comment
Я бы посоветовал поговорить с вашим администратором баз данных, похоже, что когда база данных была перемещена, некоторые сценарии не запускались, это не проблема кода, это проблема, связанная с базой данных.   -  person MethodMan    schedule 16.04.2014
comment
Пользователь определенно запускал код вставки. В этой базе нет триггеров. Любые мысли о том, как определить, была ли запись 2975 обновлением или заменой - я не ожидал ни того, ни другого.   -  person Kevin Clary    schedule 16.04.2014


Ответы (2)


Имя вашей таблицы не соответствует схеме (например, dbo.requests). Я подозреваю, что в вашей базе данных есть две разные таблицы с одинаковыми именами. Один принадлежит схеме dbo; другой по вашей схеме по умолчанию.

Разрешение имен SQL Server для неквалифицированных ссылок работает следующим образом:

  1. Проверьте пространство имен на наличие объекта с указанным именем в схеме по умолчанию, как определено текущими учетными данными подключения. Если он найден, этот объект разрешает ссылку. Иначе...

  2. Проверьте пространство имен на наличие объекта с указанным именем в схеме dbo. Если он найден, этот объект разрешает ссылку. Иначе...

  3. Если объект является хранимой процедурой, имя которой начинается с sp_, дальнейшие проверки пространства имен выполняются для базы данных master, как в шагах 1 и 2 выше.

  4. Наконец, если ссылка не была разрешена, разрешение имени завершается ошибкой.

Ваш пользователь подключается с использованием учетных данных с одной схемой по умолчанию и разрешается в таблицу с именем requests, которая принадлежит либо этой схеме, либо dbo.

Вы, с другой стороны, используете учетные данные с другой схемой по умолчанию и находите другую таблицу с тем же именем, принадлежащую либо вашей схеме по умолчанию, либо dbo.

Ссылки на объекты следует всегда уточнять по схеме по двум причинам:

  • Представление. Два исследования пространств имен, чтобы найти объект, принадлежащий dbo, который вам, вероятно, нужен, стоит вам с точки зрения производительности.
  • Кроме того, планы выполнения, включающие неквалифицированные ссылки, могут не кэшироваться, что приводит к дополнительным повторным компиляциям.

  • Наконец, вы или кто-то другой в какой-то момент выстрелите себе в ногу. Часто одна сторона выполняет одну версию хранимой процедуры, а другая — другую. Начинается веселье — «Это работает на моей машине!». Еще лучше, когда разные люди обращаются к разным версиям одной и той же таблицы, получая кажущиеся случайными ошибки относительно отсутствующих столбцов.

ОДНАКО...

Нередко :-) для столбцов identity значение свойства identity не синхронизируется с данными по разным причинам.

Итак, если вы исключили две разные разновидности одной и той же таблицы, вам нужно, чтобы ваш администратор баз данных выполнял DBCC CHECKIDENT для таблицы, чтобы вернуть счетчик таблицы identity в соответствие с максимальной отметкой в ​​таблице.

  • DBCC CHECKIDENT( {имя таблицы} , noreseed )

    сообщает о текущих значениях как счетчика identity для таблицы, так и о текущей максимальной отметке в таблице.

  • DBCC CHECKIDENT({имя таблицы}, повторное заполнение)

    повторно заполняет счетчик identity, чтобы он соответствовал максимальной отметке в таблице.

person Nicholas Carey    schedule 15.04.2014

Также возможно, что клиент переместился с одного сервера в песочницу или облако и не смог изменить файл 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() для назначения уникальных идентификаторов дополнительным записям.

person Joseph Poirier    schedule 05.04.2019