7

私はこれが前に起こるのを見たことがありません、非常に奇妙です。

開発対象のローカル SQL Server 2012 Express データベースがあります。TestDrive プラグインを使用して簡単なテスト スイートを実行し、EF v5 でデータベースにアクセスします。

データベースにレコードを挿入するテストを実行しました。テーブルには ID 1 ~ 9 の 9 行がありました。次の挿入と ID がちょうど 10000 跳ね上がりました!!!!

Id 列は次のようになります。

1, 2, 3, 4, 5, 6, 7, 8, 9, 10009

失敗した挿入でも ID がインクリメントされることはわかっていますが、テスト実行間の 5 秒間で 10,000 の挿入に失敗しなかったことを保証できます...

テーブル構造は非常にシンプルで、一連の列と 1 つの自動インクリメント、タイプbigint(long) の ID 列、SP、トリガー、またはその他のプログラム コンテンツはありません。

[Id] [bigint] IDENTITY(1,1) NOT NULL,

非常に紛らわしいです、他の誰かがこれが起こっているのを見ましたか?

4

2 に答える 2

2

このブログ投稿には、いくつかの追加の詳細があります。2012年のようですidentityが、シーケンスとして実装されています。デフォルトでは、シーケンスにはキャッシュがあります。キャッシュが失われると、キャッシュ内のシーケンス値が失われます。

提案された解決策は、次のシーケンスを作成することno cacheです。

CREATE SEQUENCE TEST_Sequence
    AS INT
    START WITH 1
    INCREMENT BY 1
    NO CACHE

私が見る限り、ID 列の背後にあるシーケンスは見えません。プロパティを変更してキャッシュを無効にすることはできません。

これを Entity Framework で使用するには、主キーをStoredGeneratedPatternに設定しComputedます。instead of insert次に、トリガーでサーバー側の ID を生成できます。

if exists (select * from sys.sequences where name = 'Sequence1')
    drop sequence Sequence1
if exists (select * from sys.tables where name = 'Table1')
    drop table Table1
if exists (select * from sys.triggers where name = 'Trigger1')
    drop trigger Trigger1
go
create sequence Sequence1
    as int
    start with 1
    increment by 1
    no cache
go
create table Table1
    (
    id int primary key,
    col1 varchar(50)
    )
go
create trigger Trigger1
    on Table1
    instead of insert
as
insert  Table1
        (ID, col1)
select  next value for Sequence1
,       col1
from    inserted
go
insert Table1 (col1) values ('row1');
insert Table1 (col1) values ('row2');
insert Table1 (col1) values ('row3');

select  * 
from    Table1

より良い解決策を見つけたら、私に知らせてください:)

于 2012-12-01T08:28:56.267 に答える