SQL ServerEntity Framework Core 使用HiLo生成主键

HiLo是以NHibernate中生成主键的平种植办法,不过本我们得以Entity
Framework Core中使。所以当马上首内容被,我以为而在介绍如何当Entity
Framework Core中行使HiLo生成主键。

什么是Hilo?

HiLo是High Low的简写,翻译成汉语叫高低位模式。

HiLo是由“Hi”和“Lo”两组成部分转主键的平栽模式。“Hi”部分源数据库,“Lo”部分在内存中生成因为创造唯一值。请牢记,“Lo”是一个限量数字,如0-100。因此,当“Hi”部分用了“Lo”范围时,再次开展数据库调用以获得下一个“Hi数字”。故HiLo模式的长在于你事先可了解主键的值,而未用每次都和一再库据发生相互

小结出以下四点:

  1. “Hi”部分由于数据库分配,两单冒出请求保管收获唯一的总是值;
  2. 若获得“Hi”部分,我们还待理解“incrementSize”的价值(“Lo”条目的数);
    “Lo”取之克:[0,incrementSize];
  3. 标识范围之公式是:(Hi – 1) * incrementSize) + 1(Hi –
    1) * incrementSize) + incrementSize)
  4. 当有着“Lo”值使用完时,需要再打数据库中取出一个新的“Hi”值,并以“Lo”部分重置为0。

在这边演示在点滴独冒出事务中的例证,每个事情插入多个实体:

Sql Server 序列

每当EF Core中使用HiLo生成主键,我们还需了解Sql
Server中一个定义序列(Sequence)

队是于SQL Server
2012惨遭引入的(不了Oracle很已经已经落实了http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_6015.htm)。序列是用户定义的靶子,它根据创造的属性生成一密密麻麻数值。它和
Identity 列相似,但其之间时有发生好多不同之处。例如,

  • 排用于转移数据库范围之序列号;
  • 队列不与一个表相关联,您可用那同大多独说明相关联;
  • 其可用来插入语句来插入标识值,也可以以T-SQL脚论被动用。

创行示例的SQL语句:

Create Sequence [dbo].[Sequence_Test] 
As [BigInt]         --整数类型
Start With 1        --起始值
Increment By 1      --增量值
MinValue 1          --最小值
MaxValue 9999999    --最大值
Cycle               --达到最值循环 [ CYCLE | NO CYCLE ]
Cache  5;           --每次取出5个值缓存使用 [ CACHE [<常量>] | NO CACHE ]

下示例:

Create Table #T(Id BigInt Primary Key,[Time] DateTime);

Insert Into #T
            ( Id , Time )
Values      ( NEXT VALUE FOR [dbo].[Sequence_Test] , -- Id - bigint
              GetDate()  -- Time - datetime
              )
Go 10


Select * From #T

查询结果:

Id Time
1 2017-11-23 16:46:50.613
2 2017-11-23 16:46:50.643
3 2017-11-23 16:46:50.667
4 2017-11-23 16:46:50.677
5 2017-11-23 16:46:50.687
6 2017-11-23 16:46:50.697
7 2017-11-23 16:46:50.707
8 2017-11-23 16:46:50.717
9 2017-11-23 16:46:50.730
10 2017-11-23 16:46:50.740

有关序列更多的情,可以翻如下材料:

  • http://www.cnblogs.com/CareySon/archive/2012/03/12/2391581.html
  • http://www.cnblogs.com/dotnet261010/p/7082852.html
  • http://sqlhints.com/2015/08/01/difference-between-sequence-and-identity-in-sql-server/
  • https://raresql.com/2012/05/01/difference-between-identity-and-sequence/

运HiLo生成主键

于咱们看如何下HiLo在Entity Framework Core中生成主键。

为了演示,我们创建了有限独从未关联之实体。

    public class Category
    {
        public int CategoryID { get; set; }
        public string CategoryName { get; set; }
    }

    public class Product
    {
        public int ProductID { get; set; }
        public string ProductName { get; set; }
    }

恳请记住,EF Core按老规矩配置一个称作吧Id<type
name>Id
作实体的主键属性。现在我们要创造我们的DBContext,在这边我们创建SampleDBContext.cs类:

public class SampleDBContext : DbContext
{
    public SampleDBContext()
    {
        Database.EnsureDeleted();
        Database.EnsureCreated();
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder)
    {
            var sqlConnectionStringBuilder = new SqlConnectionStringBuilder {
                DataSource = "****",
                InitialCatalog = "EFSampleDB",
                UserID = "sa",
                Password = "***"
            };
            optionsBuilder.UseSqlServer(sqlConnectionStringBuilder.ConnectionString);

    }

    protected override void OnModelCreating(ModelBuilder modelbuilder)
    {
        modelbuilder.ForSqlServerUseSequenceHiLo("DBSequenceHiLo");
    }

    public DbSet<Product> Products { get; set; }
    public DbSet<Category> Categories { get; set; }
}
  • SampleDBContext构造函数初始化数据库,类型于EF
    6被之DropCreateDatabaseAlways
  • OnConfiguring() 方法用于配置数据库链接字符串;
  • OnModelCreating方式用于定义实体模型。要定义HiLo序列,请以ForSqlServerUseSequenceHiLo扩大方法。您需提供序列的称谓。

运行应用程序,您当当开创“EFSampleDB”数据库被观看Product表、Category表和DBSequenceHiLo序列。

以下是创造DBSequenceHiLo的脚本。

Create Sequence [dbo].[DBSequenceHiLo] 
 As [BigInt]
 Start With 1
 Increment By 10
 MinValue -9223372036854775808
 MaxValue 9223372036854775807
 Cache 
Go

正而您所观看的,它自从1发端,递增是10。

本通往数据库被补充加有数量。以下代码首先补充加3单Category实业和调用SaveChanges(),然后上加3单Product实业并调用SaveChanges()

    using (var dataContext = new SampleDBContext())
    {
        dataContext.Categories.Add(new Category() { CategoryName = "Clothing" });
        dataContext.Categories.Add(new Category() { CategoryName = "Footwear" });
        dataContext.Categories.Add(new Category() { CategoryName = "Accessories" });
        dataContext.SaveChanges();
        dataContext.Products.Add(new Product() { ProductName = "TShirts" });
        dataContext.Products.Add(new Product() { ProductName = "Shirts" });
        dataContext.Products.Add(new Product() { ProductName = "Causal Shoes" });
        dataContext.SaveChanges();
    }

当这个代码第一坏受实践,Clothing
实体通过Add术增加及DBContext常常,就会向数据库调用获取序列的值,我们啊得透过SQL
Server Profiler来证实其。

次调用dataContext.SaveChanges()时,3个Category实体将被保存。查看执行之SQL语句。主键值已经让转,序列值的获得也惟有实行了一样糟。

就算插入3个Product实体,序列值也不见面自数据库中赢得。只有当插入10长达记下(Lo部分耗尽)时,才见面朝数据库调用获得下一个(Hi部分)序列值。

为HiLo运用到么实体

面的代码两只说明共用一个HiLo序列。如果你就想对一个特定的说明,那么你可以应用下的代码。

    modelbuilder.Entity<Category>().
            Property(o => o.CategoryID).ForSqlServerUseSequenceHiLo();

及时段代码用创一个默认名称为“EntityFrameworkHiLoSequence”的新序列,因为尚未点名名字。您为得以定义多独HiLo序列。例如:

    protected override void OnModelCreating(ModelBuilder modelbuilder)
    {
        modelbuilder.ForSqlServerUseSequenceHiLo("DBSequenceHiLo");
        modelbuilder.Entity<Category>()
                .Property(o => o.CategoryID).ForSqlServerUseSequenceHiLo();
    }

以数据库中,将创设两独队。Category实体将运EntityFrameworkHiLoSequence序号,所有其他实体使用DBSequenceHiLo序列。

配置HiLo序列

ForSqlServerHasSequence扩充方法无能够改变起始值和增量值的挑选项。但是,有一样栽办法来定义这些选择。首先,使用HasSequence道定义序列的StartAtIncrementBy挑选,然后再度用ForSqlServerUseSequenceHiLo()扩展方法,要保障序列的名相同。例如:

    modelbuilder.HasSequence<int>("DBSequenceHiLo")
                      .StartsAt(1000).IncrementsBy(5);
    modelbuilder.ForSqlServerUseSequenceHiLo("DBSequenceHiLo");

以这种状况下,生成DBSequenceHiLo的剧本如下。

CREATE SEQUENCE [dbo].[DBSequenceHiLo] 
 AS [int]
 START WITH 1000
 INCREMENT BY 5
 MINVALUE -2147483648
 MAXVALUE 2147483647
 CACHE 
GO

于是当我们实践同样之代码插入3独Category实业,那么主键的价值将于1000始。

与此同时由于IncrementBy择设置也“5”,所以当于左右文中添加第6个插入时,将开展数据库调用以得下一个序列值。以下是插3只Category实体然后插入3单之Product实业时SQL
Server
profiler的屏幕截图,您可以观看数据库调用获取序列的下一个价的次数是2不良。

要是您对在Entity Framework
Core中采用HiLo生成主键感兴趣,不防自己动手测试一下。

参考资料:

  • https://vladmihalcea.com/2014/06/23/the-hilo-algorithm/
  • http://www.talkingdotnet.com/use-hilo-to-generate-keys-with-entity-framework-core/

相关文章