Entity Framework Core 使用HiLo生成主键。Entity Framework Core 1.1 Preview 1 简介。

by admin on 2018年10月5日

HiLo是当NHibernate中生成主键的平等种植方式,不过本我们得在Entity
Framework Core中利用。所以当当时篇内容遭,我拿向你在介绍如何当Entity
Framework Core中行使HiLo生成主键。

实业框架核心(EF Core)是Entity
Framework的一个轻量级,可扩大以及跨平台版本。 10月25日,Entity Framework
Core 1.1 Preview 1发布了。

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

每当此处演示在点滴个冒出事务中之例证,每个工作插入多单实体:

亚洲必赢手机 1

升级到Entity Framework Core 1.1 Preview 1

倘你使用由EF团队(SQL
Server,SQLite和InMemory)提供的数据库提供次之一,则单纯需要提升提供程序包。

PM> Update-Package Microsoft.EntityFrameworkCore.SqlServer –Pre
如果您使用的是第三方数据库提供程序,请检查它们是否已发布依赖于1.1.0-preview1-final的更新。 如果他们有,那么只是升级到新版本。 如果没有,那么你应该只能升级它们依赖的EF Core关系组件。 1.1中的大部分新功能不需要更改数据库提供程序。 EF开发组做了一些测试,以确保依赖于1.0的数据库提供程序继续使用1.1预览1,但这个测试还不详尽。

 
PM> Update-Package Microsoft.EntityFrameworkCore.Relational –Pre

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/

升级tooling packages

一经您利用的家伙确保,那么势必要是升迁。
请注意,工具版本化为1.0.0-preview3-final,因为工具没有达其开稳定版本(在.NET
Core,ASP.NET Core和EF Core上之工具还是这样)。

PM> Update-Package Microsoft.EntityFrameworkCore.Tools –Pre
如果您使用的是ASP.NET Core,那么您需要更新project.json的tools部分以使用新的Microsoft.EntityFrameworkCore.Tools.DotNet包。 随着.NET CLI工具的设计的进行,我们必须将dotnet ef工具分离到这个单独的包中。
"tools": {
  "Microsoft.EntityFrameworkCore.Tools.DotNet": "1.0.0-preview3-final"
},

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

亚洲必赢手机 2

以下是开创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来说明其。
亚洲必赢手机 3

次调用dataContext.SaveChanges()时,3个Category实业将让封存。查看执行的SQL语句。主键值已经于转移,序列值的获取也仅实行了一样软。
亚洲必赢手机 4

哪怕插入3只Product实业,序列值也未会见自数据库被落。只有当插入10久记下(Lo部分耗尽)时,才见面于数据库调用获得下一个(Hi部分)序列值。

什么是Entity Framework Core 1.1 Preview 1

1.1本专注于解决阻碍人们使用EF Core的题目。
这包括修复错误并累加一些并未在EF Core中实现的基本点意义。
虽然EF开发组在这上头取得了部分名特优的展开,但是,EF
Core仍然不见面是每个人之是抉择。 有关落实之更多详细信息,请参见下面的EF
Core和EF6.x比较。

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

亚洲必赢手机 5

EF Core和EF6.x比较

生点儿独版本的Entity Framework,Entity Framework Core和Entity Framework
6.x.

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

亚洲必赢手机 6

而由于IncrementBy慎选设置为“5”,所以当于上下文中添加第6只插入时,将展开数据库调用以抱下一个序列值。以下是插3单Category实体然后插入3只底Product实体时SQL
Server
profiler的屏幕截图,您得看出数据库调用获取序列的产一个价值的次数是2不行。
亚洲必赢手机 7

倘若您对以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/

Entity Framework 6.x

Entity Framework
6.x(EF6.x)是一致栽经过试验与测试的多寡访问技术,具有多年之成效跟安静。
它首软以2008年发表,作为.NET Framework 3.5 SP1和Visual Studio 2008
SP1的一模一样有的。 从EF4.1本开始,它当EntityFramework NuGet包发运 –
目前是NuGet.org上无与伦比被欢迎的保管。

EF6.x继续是一个让支持之产品,并以连续进行不当修复与多少之改善。

Entity Framework Core

实业框架核心(EF Core)是Entity
Framework的一个轻量级,可扩大以及跨平台版本。 与EF6.x相比,EF
Core引入了森改良和新力量。 同时,EF Core 是一个初的代码基础

EF Core保留了自EF6.x的开发者体验,大多数一等API也维持无转移,因此EF
Core对使用EF6.x的用户会深感分外熟悉。 同时,EF
Core构建了平等模拟新的主干零部件。 这代表EF
Core不会见自动继承EF6.x的备力量。
其中一部分功能以以未来版中显示(例如延迟加载与连接弹性),其他较非常用之功力将非见面当EF
Core中落实。

初的,可扩大的以及轻量级核心还同意我们当EF核心中补充加有以EF6.x中莫克促成之风味(例如在LINQ查询中的备用密钥和混合客户端/数据库评估)。

改进LINQ翻译

以1.1版本被,EF研发团队于改善EF Core LINQ提供次方面获得了美妙的开展。
这使再多的查询能够得逞实践,在数据库(而休是内存)中评估更多之逻辑。

DbSet.Find

DbSet.Find(…)是一个存于EF6.x被的API,并且是EF
Core的再广大的伸手之一。 它同意你根据主键值轻松查询实体。
如果实体已经加载到上下文中,则归其而未查询数据库。

using (var db = new BloggingContext())
{
    var blog = db.Blogs.Find(1);
}

投到字段(Mapping to fields)

API中的新的HasField(…)方法允许而为性配置备用字段。
这是无比广的做法是当一个性没有setter。

public class BloggingContext : DbContext
{
    ...

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.Property(b => b.Url)
.HasField(“_theUrl”);
}
}

默认情况下,EF将在查询期间构造实体的实例时使用该字段,或者当它无法使用该属性时(即,它需要设置值,但没有属性设置器)。 您可以通过新的UsePropertyAccessMode(...)API更改。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Url)
        .HasField("_theUrl")
        .UsePropertyAccessMode(PropertyAccessMode.Field);
}

君还好于范中开创于实体类吃从不相应属性之属性,但利用字段将数据存储在实业中。
这同“阴影属性”(下面介绍,距离这里12cm)不同,数据存储于转跟踪器中。
如果实体类使用方法来得到/设置值,则一般用此方式。

你得于性能(…)API中给EF字段的称号。
如果没有具备给定名称的性,则EF将寻找一个字段。

public class BloggingContext : DbContext
{
    ...

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
.Property(“_theUrl”);
}
}

您还可以选择为该属性指定名称,而不是字段名称。 然后在创建模型时使用此名称,最明显的是它将用于映射到数据库中的列名称。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property<string>("Url")
        .HasField("_theUrl");
}
您可以使用EF.Property(...)方法在LINQ查询中引用这些属性。
var blogs = db.Blogs
    .OrderBy(b => EF.Property<string>(b, "Url"))
    .ToList();
 

阴影属性(Entity Framework Core)

阴影属性是实体类中莫在的性质。
这些性之价与状态了保存在转移跟踪器中

可以通过ChangeTracker API获取与反阴影属性值。

context.Entry(myBlog).Property("LastUpdated").CurrentValue = DateTime.Now;
阴影属性可以通过EF.Property静态方法在LINQ查询中引用。
var blogs = context.Blogs
    .OrderBy(b => EF.Property<DateTime>(b, "LastUpdated"));

影子属性约定(Conventions Shadow Properties)

本惯例,仅当发现涉嫌经常才创建阴影属性,但于直属实体类中检索不交外键属性。
在这种情景下,将引入影子外键属性。
shadow外键属性将命名为<navigation property name><principal
key property
name>
(在凭借实体上的领航,它对主体实体,用于命名)。
如果主键属性名称包含导航属性的称号,则称将只是<principal key
property name>

如果从属于实体上尚未导航属性,则于那职运用主类型名称。

譬如说,以下代码清单将造成向Post实体引入BlogId shadow属性。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public Blog Blog { get; set; }
}

影子属性数据注释

没辙以数据注释创建阴影属性。

黑影属性Fluent API

若得运用Fluent API配置阴影属性。
一旦而调用了Property的字符串重载,你尽管足以链接任何针对其它性能之配置调用。

假如提供于Property方法的名目及现有属性(阴影属性或实体类及定义的性质)的称号匹配,则代码用布现有属性,而休是引入新的shadow属性。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property<DateTime>("LastUpdated");
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

影子属性介绍了!

 

显式加载

显式加载允许而加载由上下文跟踪的实体的领航属性之始末。

using (var db = new BloggingContext())
{
    var blog = db.Blogs.Find(1);

db.Entry(blog).Collection(b => b.Posts).Load();
db.Entry(blog).Reference(b => b.Author).Load();
}

来自EF6.x的其他EntityEntry API

EF研发集团上加了EF6.x中提供的其余EntityEntry API。
这包Reload(),GetModifiedProperties(),GetDatabaseValues()等。这些API最常用的凡由此调用DbContext.Entry(对象实体)方法。

连日来弹性

接连弹性自动重试失败的数据库命令。 此版本包括把为SQL Server(包括SQL
Azure)定制的推行策略。 此执行策略包含在我们的SQL Server提供程序中。
它了解可以重试的要命类型,并且有着强烈的默认值,用于最可怜重试次数,重试之间的缓等。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(
        "<connection string>",
        options => options.EnableRetryOnFailure());
}

其它数据库提供者可以选丰富为该数据库定制的重试策略。
还时有发生同样种体制来注册自己的自定义执行策略。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseMyProvider(
        "<connection string>",
        options => options.ExecutionStrategy(...));
}

 

SQL Server内存优化表支持

内存优化表是SQL Server的均等宗功能。
您现在可指定实体映射到的阐明是内存优化的。 当使用EF
Core基于你的模型(使用迁移或Database.EnsureCreated)创建同掩护数据库时,将为这些实体创建一个内存优化表。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ForSqlServerIsMemoryOptimized();
 }
 

简化服务转移

以EF Core
1.0遇,可以替换EF使用的中间服务,但马上是复杂的,需要您控制EF使用的依赖注入容器。
在1.1惨遭,我们采用了一个ReplaceService(…)方法,可以当配备上下文时使用它们。

public class BloggingContext : DbContext
{
    ...

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{


optionsBuilder.ReplaceService();
}
}

Entity Framework Core 1.1 Preview 1的前途版本

稳定的1.1本用为当年晚些时候推出。
EF研发集团不计划于preview1和安宁版本里添加其它新效能。
将只是用力修复报告的谬误。

EF研发团队现在以注意力转移到EF Core 1.2与EF6.2本子。
将于快之明天享受这些本子的详细信息。

 

贴平摆Rowan
Miller的帅照。Microsoft员工,EF研发团队成员,他的个人Blog:https://romiller.com/,有趣味的朋友可以错过探访。

亚洲必赢手机 8

最后,希望本文对你具备帮助。

转载请注明出处,转载请注明出处,转载请注明出处,重要的政工说其三百分之百:http://www.cnblogs.com/smallprogram/

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图