Hi / Loアルゴリズムは、一意のキーが必要な場合に便利です。 つまり、Hi / Loアルゴリズムは、データベースではなくクライアント側でセキュアな識別子を生成するためのメカニズムを記述します(
このコンテキストで安全とは、衝突がないことを意味します )。 行がデータベースにすぐに保存されるかどうかに依存せず、テーブルの行に一意の識別子を設定します。 これにより、通常の順次データベース識別子のように、識別子をすぐに使用できます。
データベース
シーケンスはキャッシュされ、スケーリングされ、同時実行の問題を解決します。 しかし、新しいシーケンス値ごとに、常にデータベースにアクセスする必要があります。 そして、大量の挿入があると、少しオーバーヘッドになります。 したがって、シーケンスの処理を最適化するために、Hi / Loアルゴリズムが使用されます。 EntityFramework Coreは、
ForSqlServerUseSequenceHiLo
メソッドを使用して、
ForSqlServerUseSequenceHiLo
Hi / Loをサポートします
Hi / Loの仕組み
まず、
Hi / Loとは
何ですか 。 基本的な考え方は、主キーを構成する2つの数字、つまり「高」(
高 )番号と「低」(
低 )番号があるということです。 クライアントは基本的に、「高」シーケンスを増やすことができます。これは、以前の「高」値の範囲全体から、多くの「低」値を持つキーを安全に生成できることを知っています。
たとえば、現在の値が35の「高い」シーケンスがあり、「低い」数値の範囲が0〜1023であるとします。 次に、クライアントはシーケンスを36に増やし(他のクライアントが35を使用するときにキーを生成できるように)、キー35 / 0、35 / 1、35 / 2、35 / 3 ... 35/1023がすべて使用可能であることを知ることができます。
主キーなしで値を挿入してからクライアントに取得する代わりに、クライアント側で主キーを設定できると(特にORMを使用して)非常に便利です。 とりわけ、これは、挿入を行う前に親と子の間の関係を簡単に作成し、すべてのキーを適切に配置できることを意味します。これにより、バッチ処理が
容易になります。
Hi / Loを使用して、Entity Framework Coreでキーを生成します
Entity Framework Coreを使用して、Hi / Loを使用してキーを生成する方法を見てみましょう。 カテゴリーの単純なモデルがあるとしましょう:
public class Category { public int Id { get; set; } public string Name { get; set; } }
EFは
Id
プロパティまたは
< >Id
をキーとして構成することに注意してください。 次に、DBContextを作成する必要があります。
public class SampleDBContext : DbContext { public SampleDBContext() { Database.EnsureDeleted(); Database.EnsureCreated(); } protected override void OnConfiguring(DbContextOptionsBuilder optionBuilder) { string onnString = @"Server=localhost\SQLEXPRESS01;Database=EFSampleDB;Trusted_Connection=true;"; optionBuilder.UseSqlServer(onnString); } protected override void OnModelCreating(ModelBuilder modelBuilder) { var entityTypeBuilder = modelBuilder.Entity<Category>(); entityTypeBuilder.ToTable("Category"); entityTypeBuilder.HasKey(t => t.Id); entityTypeBuilder.Property(t => t.Id).ForSqlServerUseSequenceHiLo(); entityTypeBuilder.Property(t => t.Name).HasMaxLength(128).IsRequired(); } public DbSet<Category> Category { get; set; } }
DbContextの構成:
DropCreateDatabaseAlways
データベースDropCreateDatabaseAlways
実装であるDropCreateDatabaseAlways
。OnConfiguring
を構成するOnConfiguringメソッド。OnModelCreating
メソッドは、モデルの構成を決定できる場所です。 Hi / Loシーケンスを決定するには、 ForSqlServerUseSequenceHiLo
拡張ForSqlServerUseSequenceHiLo
使用します。
アプリケーションを起動します。 そのため、EFSampleDBデータベースは、CategoryテーブルとシーケンスEntityFrameworkHiLoSequenceを使用して作成する必要があります。 シーケンスの名前と、それが作成されるスキームをパラメーターとして渡すことができます。
ForSqlServerUseSequenceHiLo(string name, string schema)
。
「EntityFrameworkHiLoSequence」を作成するためのスクリプトは次のようになります
CREATE SEQUENCE [dbo].[EntityFrameworkHiLoSequence] AS [bigint] START WITH 1 INCREMENT BY 10 MINVALUE -9223372036854775808 MAXVALUE 9223372036854775807 CACHE GO
このシーケンスは1から始まり、10ずつ増加します
INCREMENT BY
オプションと比較すると、
Sequenceと
Hi / Lo Sequenceには違いがあります。
シーケンスでは、 INCREMENT BY
は
シーケンスの以前の値に値を追加して新しい値を生成します。 したがって、この場合、前のシーケンス値が11の場合、次のシーケンス値は11 + 10 = 21になります
INCREMENT BY
/ Loシーケンスの場合 、
INCREMENT BY
パラメーターはブロックの値を示します。つまり、次のシーケンス値が選択されます最初の10を使用します。
データベースにいくつかのデータを追加しましょう。
using (var dataContext = new SampleDBContext()) { dataContext.Category.Add(new Category { Name = "Name-1" }); dataContext.Category.Add(new Category { Name = "Name-2" }); dataContext.Category.Add(new Category { Name = "Name-3" }); dataContext.SaveChanges(); }
このコードがカテゴリがDBContextに追加される行に到達するとすぐに、データベースが呼び出されてシーケンス値が取得されます。 これは、SQL Server Profilerを使用して確認できます。

dataContext.SaveChanges();
が呼び出されたとき
dataContext.SaveChanges();
3つのカテゴリはすべて、すでに生成されて1回だけ選択されている主キー値とともに保存されます。

Lo部分がなくなるまでデータベースからシーケンス値は選択されません(この例では10レコード)。11番目のレコードを追加するときのみ、次のシーケンス値(Hi)を取得するためにデータベースが呼び出されます。
複数のテーブルからなる1つのシーケンスを作成できます。
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ForSqlServerUseSequenceHiLo("DBSequenceHiLo"); }
Hi / Loシーケンス設定
ForSqlServerHasSequence
メソッドには、初期値と増分値を変更するためのパラメーターがありません。 ただし、これらの値は次のように指定できます。まず、
StartAt
パラメーターと
IncrementBy
パラメーターを使用してシーケンスを決定し、次に同じ
ForSqlServerUseSequenceHiLo
拡張
ForSqlServerUseSequenceHiLo
を使用します。
modelBuilder.HasSequence<int>("DBSequenceHiLo").StartsAt(1000).IncrementsBy(5); modelBuilder.ForSqlServerUseSequenceHiLo("DBSequenceHiLo");
この場合、DBSequenceHiLoのsqlスクリプトは次のようになります。
CREATE SEQUENCE [dbo].[DBSequenceHiLo] AS [int] START WITH 1000 INCREMENT BY 5 MINVALUE -2147483648 MAXVALUE 2147483647 CACHE GO
ここで、3つのカテゴリを追加すると、キー値は1000で始まります。また、
IncrementBy
パラメーターが「5」に設定されているため、6番目のレコードがコンテキストに追加されると、シーケンスの次の値を取得するためにデータベースに要求が行われます。 コードを変更してさらに3つのカテゴリを追加すると、画面に2番目のデータベース呼び出しが表示されます。

ご清聴ありがとうございました!