欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

Entity Framework Core 使用HiLo生成主键

发布时间:2023/12/4 编程问答 70 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Entity 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模式的优点在于您预先可以知道主键的值,而不用每次都与数库据发生交互

总结有以下四点:

  • “Hi”部分由数据库分配,两个并发请求保证得到唯一的连续值;

  • 一旦获取“Hi”部分,我们还需要知道“incrementSize”的值(“Lo”条目的数量);
    “Lo”取的范围:[0,incrementSize];

  • 标识范围的公式是:(Hi - 1) * incrementSize) + 1 到 (Hi - 1) * incrementSize) + incrementSize)

  • 当所有“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 - bigintGetDate()  -- Time - datetime)Go 10Select * 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 1Increment By 10MinValue -9223372036854775808MaxValue 9223372036854775807Cache 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方法定义序列的StartAt和IncrementBy选项,然后再使用ForSqlServerUseSequenceHiLo()扩展方法,要保持序列的名称一致。例如:

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

    在这种情况下,生成DBSequenceHiLo的脚本如下。

    CREATE SEQUENCE [dbo].[DBSequenceHiLo] AS [int] START WITH 1000INCREMENT BY 5MINVALUE -2147483648MAXVALUE 2147483647CACHE 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/


    原文:http://www.cnblogs.com/tdfblog/p/entity-framework-core-hilo.html


    .NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com


    总结

    以上是生活随笔为你收集整理的Entity Framework Core 使用HiLo生成主键的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。