SQL ServerEntity Framework Core 使用HiLo生成主键

应用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推而广之方法。您需要提供体系的名号。

运转应用程序,您应该在创设“EF山姆pleDB”数据库中看看Product表、Category表和DBSequenceHiLo序列。

SQL Server 1

以下是成立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来表达它。
SQL Server 2

次调用dataContext.SaveChanges()时,3个Category实业将被封存。查看执行的SQL语句。主键值已经被变型,体系值的获取也只举办了一回。
SQL Server 3

哪怕插入3个Product实业,连串值也不会从数据库中拿到。唯有当插入10条记下(Lo部分耗尽)时,才会向数据库调用得到下一个(Hi部分)连串值。

什么是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 4

配置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发端。

SQL Server 5

还要由于IncrementBy分选设置为“5”,所以当在左右文中添加第6个插入时,将拓展数据库调用以博得下一个体系值。以下是插入3个Category实体然后插入3个的Product实体时SQL
Server
profiler的屏幕截图,您可以见到数据库调用获取类别的下一个值的次数是2次。
SQL Server 6

假诺你对在Entity Framework
Core中运用HiLo生成主键感兴趣,不防自己下手测试一下。

参考资料:

HiLo是在NHibernate中生成主键的一种办法,但是现在我们可以在Entity
Framework Core中利用。所以在这篇内容中,我将向你在介绍如何在Entity
Framework Core中运用HiLo生成主键。

向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序列。

SQL Server 7

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

关于连串更多的情节,可以查阅如下材料:

相关文章