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模式的优点在于您预先可以知道主键的值,而不用每次都与数库据发生交互

总结有以下四点:

  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 - 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方法定义序列的StartAtIncrementBy选项,然后再使用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


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322765.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P1991-无线通讯网【最小生成树,瓶颈生成树】

正题 题目大意 有nnn个点&#xff0c;连边长度不超过DDD的情况下分为SSS个联通块。 求最小的DDD 解题思路 直接KruskalKruskalKruskal连边连到只剩下SSS个联通块就好了。 codecodecode #include<cstdio> #include<cmath> #include<algorithm> using names…

Echarts报错:Component series.lines not exists. Load it first.

前几天用的echarts标签是bootcdn的 <script src"https://cdn.bootcdn.net/ajax/libs/echarts/4.7.0/echarts-en.common.js"></script>用着官方给的案例还可以&#xff0c;但是一用gallery社区里面的例子就报错 后来经过不断调试终于知道是需要换个cdn&…

Mongodb常见问题

转载自 Mongodb常见问题 一.数据库级锁 MongoDB的锁机制和一般关系数据库如 MySQL&#xff08;InnoDB&#xff09;, Oracle 有很大的差异&#xff0c;InnoDB 和 Oracle 能提供行级粒度锁&#xff0c;而 MongoDB 2.x 只能提供 库级粒度锁&#xff0c;这意味着当 MongoDB 一个…

认识微软Visual Studio Tools for AI

微软已经发布了其 Visual Studio Tools for AI 的测试版本&#xff0c;这是微软 Visual Studio 2017 IDE 的扩展&#xff0c;可以让开发人员和数据科学家将深度学习模型嵌入到应用程序中。Visual Studio Tools for AI 工具同时支持 Microsoft 的 Cognitive Toolkit 和 Google 的…

P1297-[国家集训队]单选错位【期望概率】

正题 题目大意 nnn道题&#xff0c;第iii道aia_iai​个选项&#xff0c;选择每个选项的概率第相等的。但是每个选择都会填到后一道题。求对的期望题数。 解题思路 考虑若前面一道题有xxx个选项&#xff0c;后一道有yyy个选项&#xff0c;那么其实就是求一个在1∼x1\sim x1∼x随…

mybatis源码阅读(一):SqlSession和SqlSessionFactory

转载自 mybatis源码阅读(一)&#xff1a;SqlSession和SqlSessionFactory 一、接口定义 听名字就知道这里使用了工厂方法模式&#xff0c;SqlSessionFactory负责创建SqlSession对象。其中开发人员最常用的就是DefaultSqlSession &#xff08;1&#xff09;SqlSession接口定义…

开源纯C#工控网关+组态软件(六)图元组件

一、 图元概述 图元是构成人机界面的基本单元。如一个个的电机、设备、数据显示、仪表盘&#xff0c;都是图元。构建人机界面的过程就是铺排、挪移、定位图元的过程。 图元设计是绘图和编码的结合。因为图元不仅有显示和动画&#xff0c;还有背后操纵动画的控制逻辑。 一个好…

P2590-[ZJOI2008]树的统计【树链剖分,线段树】

正题 题目大意 一棵带权树&#xff0c;要求单点修改&#xff0c;路径求和和路径求最大值。 解题思路 先来一个树链剖分&#xff0c;然后线段树维护。 codecodecode #include<cstdio> #include<algorithm> using namespace std; const int N31000; int tot,cnt,n…

git合并分支的策略(赞)

假设当前有两个分支 master和test&#xff0c;两个分支一模一样&#xff0c;都有这三个文件 现在test添加一个test4.txt&#xff0c;然后提交到本地&#xff08;git add . git commit&#xff09; 切换到master分支上&#xff0c;git checkout master git merge test 这样mase…

mybatis源码阅读(二):mybatis初始化上

转载自 mybatis源码阅读(二)&#xff1a;mybatis初始化上 1.初始化入口 //Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互 private static SqlSessionFactory getSessionFactory() {SqlSessionFactory sessionFactory null;String …

P1983-车站分级【图论,记忆化dfs,构图】

正题 题目链接:https://www.luogu.org/problemnew/show/P1983 题目大意 一个辆车会一个一个值xxx&#xff0c;如果等级大于等于xxx的车站都会停靠(包括起点和终点)。给每辆车的停靠点&#xff0c;求至少要将车站分多少级。 解题思路 对于一辆车&#xff0c;若一个点他经过了…

slot的使用

普通插槽 在嵌入的组件标签中加入内容&#xff0c;如果子组件中有slot就显示&#xff0c;否则就是不显示 父组件 <h1>Hello 父组件</h1> <Child><p>这是一些初始内容</p><p>这是更多的初始内容</p> </Child>子组件 <h1&…

mybatis源码阅读(三):mybatis初始化(下)mapper解析

转载自 mybatis源码阅读(三)&#xff1a;mybatis初始化&#xff08;下&#xff09;mapper解析 MyBatis 的真正强大在于它的映射语句&#xff0c;也是它的魔力所在。由于它的异常强大&#xff0c;映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比…

改造独立部署(SCD)模式下.NET Core应用程序 dotnet的exe文件启动过程

设置一个小目标 改造前 改造后 独立部署SCD模式&#xff0c;是指在使用dotnet publish 命令时带上-r 参数运行时标识符&#xff08;RID&#xff09;。 目标提出原因&#xff1a;SCD模式下文件太乱了&#xff0c;很多文件在开发时大多又涉及不到&#xff0c;发布后如果能把文件…

P1268-树的重量【图论】

正题 题目大意 一棵树有nnn个叶子节点&#xff0c;给出每两个叶子节点之间的距离。求这棵树的边权之和。 解题思路 我们考虑每次加入一个节点。两个节点时不用说。 加入第三个节点时&#xff0c;肯定是加入在节点1和节点2之间。 之后我们开始推导&#xff1a;当我们加入节点…

mybatis源码阅读(四):mapper(dao)实例化

转载自 mybatis源码阅读(四)&#xff1a;mapper(dao)实例化 在开始分析之前&#xff0c;先来了解一下这个模块中的核心组件之间的关系&#xff0c;如图&#xff1a; 1.MapperRegistry&MapperProxyFactory MapperRegistry是Mapper接口及其对应的代理对象工程的注册中心&…

ajax的封装使用

面试的时候有人问到我ajax的使用&#xff0c;当时回答的不算好&#xff0c;这里想重新总结下&#xff1a; 1、如何将配置等信息传到ajax函数里面去 这个采用的是在参数里加一个对象&#xff0c;对象里面放入字段&#xff0c;然后在ajax里设置一个option&#xff0c;通过option…

P3385-[模板]负环【SPFA】

正题 题目大意 求点1可不可以走到负环。 解题思路 用cnticnt_icnti​表示到iii的最短路经过了多少个点&#xff0c;然后求若cnti≥ncnt_i\geq ncnti​≥n且这条路是负数那么就有负环。 codecodecode #include<cstdio> #include<queue> #include<cstring> …

自定义路由匹配和生成

前言 前两篇文章主要总结了CMS系统两个技术点在ASP.NET Core中的应用&#xff1a; 《ASP.NET Core 中的SEO优化&#xff08;1&#xff09;&#xff1a;中间件实现服务端静态化缓存》 《ASP.NET Core 中的SEO优化&#xff08;2&#xff09;&#xff1a;中间件中渲染Razor视图》…

mybatis多个参数(不使用@param注解情况下),sql参数占位符正确写法

转载自 mybatis多个参数(不使用param注解情况下)&#xff0c;sql参数占位符正确写法 useActualParamName配置 useActualParamName允许使用方法签名中的名称作为语句参数名称。 为了使用该特性&#xff0c;你的工程必须采用Java 8编译&#xff0c;并且加上-parameters选项。&…