Framework Core中动用HiLo生成主键。Entity Framework

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/

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/,有趣味之情侣可错过探视。

图片 1

终极,希望本文对您拥有帮助。

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

配置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起。

图片 2

并且由于IncrementBy选择设置为“5”,所以当以前后文中添加第6单插入时,将开展数据库调用以博取下一个序列值。以下是插3个Category实体然后插入3单的Product实体时SQL
Server
profiler的屏幕截图,您可望数据库调用获取序列的生一个价的次数是2软。
图片 3

若你对在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/

实业框架核心(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。

在此处演示在少个冒出事务中的事例,每个业务插入多只实体:

图片 4

黑影属性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; }
}

黑影属性介绍完!

 

应用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序列。

图片 5

以下是创办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来证实其。
图片 6

次调用dataContext.SaveChanges()时,3个Category实业将给封存。查看执行的SQL语句。主键值已经于转,序列值的落也唯有实行了扳平次于。
图片 7

就插入3只Product实业,序列值也无见面从数据库中拿走。只有当插入10漫长记下(Lo部分耗尽)时,才见面朝数据库调用获得下一个(Hi部分)序列值。

SQL Server内存优化表支持

内存优化表是SQL Server的一律项功能。
您现在得以指定实体映射到之发明是内存优化的。 当使用EF
Core基于你的型(使用迁移或Database.EnsureCreated)创建和护卫数据库时,将为这些实体创建一个内存优化表。

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

HiLo是于NHibernate中生成主键的一致栽艺术,不过本咱们好以Entity
Framework Core中运用。所以当当下篇内容遭,我拿向您于介绍如何以Entity
Framework Core中使HiLo生成主键。

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

图片 8

升级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"
},

EF Core和EF6.x比较

发点儿个版的Entity Framework,Entity Framework Core和Entity Framework
6.x.

阴影属性约定(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; }
}

显式加载

显式加载允许你加载由上下文跟踪的实体的导航属性的情节。

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();
}

升级到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

阴影属性(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"));

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继续是一个吃支持的出品,并将延续进行不当修复和不怎么之改善。

简化服务转移

当EF Core
1.0遇,可以替换EF使用的内部服务,但当下是复杂的,需要而控制EF使用的依赖性注入容器。
在1.1面临,我们下了一个ReplaceService(…)方法,可以在部署上下文时使用她。

public class BloggingContext : DbContext
{
    ...

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{


optionsBuilder.ReplaceService();
}
}

老是弹性

连续弹性自动重试失败的数据库命令。 此版本包括占为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(...));
}

 

投到字段(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();
 

来自EF6.x的其他EntityEntry API

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

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);
}

影子属性数据注释

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