База данных Windows Azure SQL - Столбец Auto Increance Identity пропускает значения

В настоящее время работает над приложением ASP.Net MVC 4 с использованием Entity Framework 5. Используется CodeFirst для начальной фазы разработки. Но теперь отключены автоматические миграции и проектирование новых таблиц напрямую с использованием SSMS и написания POCO. Все работает хорошо.

В последнее время выявлена ​​странная проблема в Production. Записи в одной из первоначально разработанных таблиц пропустили значение автоинкрементного значения более чем на 900 номеров. Это произошло 3 раза за последние 3 месяца. Отладка приложения локально, но не удалось воспроизвести. Наблюдается не какая-либо картина или тенденция.

Модель:

public class Enquiry
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public Int64 EnquiryId { get; set; }

    [Required]
    public int UserId { get; set; }

    [Required]
    public byte Bid { get; set; }

    ...

    [Required]
    public DateTime Created { get; set; }

    [Required]
    public DateTime Modified { get; set; }
}

public class EnquiryDetail
{
    [Key]
    public Int64 EnquiryId { get; set; }

    [Required]
    public int CreditScore { get; set; }

    [Required]
    public byte BidMode { get; set; }

    public virtual Enquiry Enquiry { get; set; }
}

DbContext:

public class EscrowDb : DbContext
{

    public EscrowDb()
        : base("name=DefaultConnection")
    {

    }
    public DbSet<Enquiry> Enquiries { get; set; }
    public DbSet<EnquiryDetail> EnquiryDetails { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Entity<EnquiryDetail>()
            .HasRequired<Enquiry>(ed => ed.Enquiry)
            .WithRequiredDependent(e => e.EnquiryDetail);
    }
}

Контроллер:

[Authorize]
public class EnquiryController : Controller
{
    private EscrowDb _db = new EscrowDb();

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(EnquiryViewModel core)
    {
       var enquiry = new Enquiry();
       // Some code to set properties using passed ViewModel
       ...

       var enquiryDetail = new EnquiryDetail();
       // Some code to set properties using passed ViewModel
       ...

       enquiry.EnquiryDetail = enquiryDetail;

       _db.Enquiries.Add(enquiry);
       _db.SaveChanges();
    }
}

Весь этот код работает до сих пор, за исключением того, что значение идентичности, которое пропускается спорадически большими пробелами почти 1000 номеров.

Кто-нибудь сталкивался с такой проблемой? Пожалуйста, поделитесь своими мыслями.

Ответы

Ответ 1

Вам может быть не повезло, если вам нужно устранить эти пробелы.

Я сам попал в эту проблему, когда разрабатываю/тестирую новое приложение. Я интуитивно понимаю, что происходит здесь, в sql azure, основываясь на том, что я читал о SQL Server 2012. Я не смог найти документацию об этом для sql azure.

Из того, что я прочитал, это функция, которая встречается как ошибка IMO. На сервере Sql 2012 Microsoft добавила возможность создавать последовательности. Последовательности записывают, какие значения использовались в блоках из 1000. Так что скажем, что ваша последовательность прогрессировала... 1, 2, 3, 4, 5... и затем перезагружается ваш сервер sql. Ну, последовательность уже сохранила тот факт, что блок 1-1000 уже используется, поэтому он перескакивает на следующий 1000.... так что ваше следующее значение 1001, 1002, 1003, 1004.... Это улучшает производительность вставляет при использовании последовательностей, но может привести к необычным разрывам. Это решение для вашей последовательности. При указании вашей последовательности добавьте параметр "NOCACHE", чтобы он не сохранял блоки по 1000 за раз. Подробнее см. здесь.

В этом случае проблема заключается в том, что столбцы Identity, похоже, были изменены для использования этой же парадигмы. Поэтому, когда ваш сервер или в этом случае перезагружается ваш экземпляр sql azure, вы можете получить большие пробелы (1000) в своих столбцах идентификации, поскольку он кэширует большие блоки как "используемые". Для сервера sql 2012 существует такое решение. Вы можете указать флаг запуска t272, чтобы вернуть вашу идентификационную информацию, используя парадигму старого сервера sql server 2008 r2. Проблема в том, что я не знаю (возможно, это невозможно) о том, как указать это в sql Azure. Не удается найти документацию. См. эту тему для получения дополнительной информации о SQL Server 2012.

Проверьте документацию на идентификатор здесь, в msdn. В частности, раздел "Последовательные значения после перезапуска сервера или другие сбои". Вот что он говорит:

Последовательные значения после перезагрузки сервера или других сбоев -SQL Server могут кэшировать значения идентичности по соображениям производительности, а некоторые из них назначенные значения могут быть потеряны во время сбоя базы данных или сервера перезапуск. Это может привести к разрыву в значении идентификации при вставке. Если пробелы неприемлемы, то приложение должно использовать последовательность генератор с опцией NOCACHE или использовать собственный механизм для генерировать значения ключа.

Итак, если вам нужно иметь последовательные значения, вы можете попробовать указать последовательность с nocache вместо того, чтобы полагаться на свой столбец идентичности. Не пробовал это сам, но звучит так, как будто вам не удастся заставить это работать с инфраструктурой сущностей.

Извините, если это мало помогает, но, по крайней мере, это информация о том, что вы переживаете.

Ответ 2

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

USE [TEST]

CREATE TABLE TEST(ID INT IDENTITY(1,1),VAL VARCHAR(10))

CREATE TRIGGER TGR_TEST_IDENTITY ON TEST
FOR INSERT
AS
DECLARE @RESEEDVAL INT
SELECT @RESEEDVAL = MAX(ID) FROM TEST
DBCC CHECKIDENT('TEST', RESEED, @RESEEDVAL)

INSERT INTO TEST(VAL)VALUES('a')

SELECT * FROM TEST

Так как "DBCC CHECKIDENT" не поддерживается в Azure, теперь вы можете использовать подход в этой ссылке В этой ссылке я нашел работу вокруг

  • Используйте ключ GUID как ключ при использовании автоматического ключа вашего SqlAzure
  • Если целочисленный ключ, такой как мой случай, позволяет вставить запись и вернуться и удалить ее, а затем вставить ее правой клавишей, используя Turing из идентификатора с set identity_insert XXXTable on - это в основном отключает IDENTITY

а затем снова верните идентификатор, когда я пройду с вставкой правой клавишей, используя

установить identity_insert XXXTable off - это в основном включает IDENTITY

Примечание. Это нехорошее решение для таблицы, которая получает массивный запрос на вставку, но может быть полезна для тех, кто ищет временный выход.

Ответ 3

Кажется, что TF 272 не работает для SQL Azure. Я просто заметил проблему в двух таблицах (пробелы 999 и 1000) и подумал, что это нарушение безопасности, прежде чем проверять две таблицы и проверять вставленные записи. Подробнее см. Последний элемент эту дискуссию MS TechNet. Вид повторного подтверждения, но выглядит скорее как ошибка, чем функция.

Ответ 4

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