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

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/

相关文章

admin

网站地图xml地图