HTML5技术

Entity Framework Core 使用HiLo生成主键 - Sweet-Tang

字号+ 作者:H5之家 来源:H5之家 2017-11-27 10:14 我要评论( )

HiLo是在NHiernate中生成主键的一种方式,不过现在我们可以在Entity Framework Core中使用。所以在这篇内容中,我将向您在介绍如何在Entity Framework Core中使用HiLo生成主键。 什么是Hilo? HiLo是High Low的简写,翻译成中文叫高低位模式。 HiLo是由“Hi

HiLo是在NHiernate中生成主键的一种方式,不过现在我们可以在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很早就已经实现了)。序列是用户定义的对象,它根据创建的属性生成一系列数值。它与 Identity 列相似,但它们之间有很多不同之处。例如,

    创建序列示例的SQL语句:

    Create Sequence [dbo].[Sequence_Test] ; --每次取出5个值缓存使用 [ CACHE [<常量>] | NO CACHE ]

    使用示例:

    ,[Time] DateTime); Insert Into #T ( Id , Time ) [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

    关于序列更多的内容,可以查阅如下资料:

    使用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; } }

    运行应用程序,您应该在创建“EFSampleDB”数据库中看到Product表、Category表和DBSequenceHiLo序列。

    以下是创建DBSequenceHiLo的脚本。

    Create Sequence [dbo].[DBSequenceHiLo] As [BigInt] -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();

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 使用AspectCore动态代理 - Lemon丶

      使用AspectCore动态代理 - Lemon丶

      2017-11-21 11:01

    • 极简版ASP.NET Core学习路径及教程 - 腾飞(Jesse)

      极简版ASP.NET Core学习路径及教程 - 腾飞(Jesse)

      2017-11-17 14:02

    • 讨论.NET Core 配置对GC 工作模式与内存的影响 - YOYOFx

      讨论.NET Core 配置对GC 工作模式与内存的影响 - YOYOFx

      2017-11-15 10:05

    • ASP.NET Core集成现有系统认证 - 腾飞(Jesse)

      ASP.NET Core集成现有系统认证 - 腾飞(Jesse)

      2017-11-14 12:40

    网友点评
    a