Framework Core中动用HiLo生成主键

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

图片 1

开创上下文 

开创的BooksContext类完结Book表与数据库的关系。那一个类派生自基类DbContext,BooksContext类定义Books属性类型为DbSet
<Book>。此类型允许成立查询并增多Book实例以将其储存在数据库中。要定义连接字符串,能够重写DbContext的OnConfiguring方法。UseSqlServer扩展方法将左右文映射到SQL
Server数据库(代码文件BooksSample / BooksContext.cs卡塔 尔(阿拉伯语:قطر‎:

public class BooksContext: DbContext
{
  private const string ConnectionString =  @"server= (localdb)\MSSQLLocalDb;database=Books;trusted_connection=true";
  public DbSet<Book> Books { get; set; }
  protected override void OnConfiguring(DbContextOptionsBuilder  optionsBuilder)
  {
    base.OnConfiguring(optionsBuilder);
    optionsBuilder.UseSqlServer(ConnectionString);
  }
}

概念连接字符串的另三个选项是运用信任注入,将在本章后边介绍。 

Sql Server 序列

在EF Core中选用HiLo生成主键,我们还索要精通Sql
Server中二个定义序列(Sequence)

队列是在SQL Server
2013中引进的(不过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

至于连串更加多的内容,可以查看如下材质:

删去记录

终极,让我们清理数据库并删除全体记录。能够因此查找全部记录并调用Remove或RemoveRange方法来安装上下文中要去除的对象的意况。然后调用SaveChangesAsync方法就能够从数据库中去除记录,DbContext会为各类要删减的靶子调用SQL
Delete语句(代码文件Books萨姆ple / Program.cs卡塔尔:

private async Task DeleteBooksAsync()
{
  using (var context = new BooksContext())
  {
    var books = context.Books;
    context.Books.RemoveRange(books);
    int records = await context.SaveChangesAsync();
    WriteLine($"{records} records deleted");
  }
  WriteLine();
}

*注意 对象关联映射工具(如Entity
Framework卡塔 尔(英语:State of Qatar)在并非在享有方案中都可用。使用示例代码不大概有效地删除全部目的。您能够采纳叁个SQL语句删除全体并不是逐一删除笔录。在第37章“ADO.NET”中解释了哪些形成那一点。*

打探了怎样增加、查询、更新和删除记录,本章将介绍幕后的效用,并接收Entity
Framework步向高级场景。

配置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生成主键感兴趣,不防自身出手测量检验一下。

参谋资料:

创制模型  

本章的首先个示例映射单个表。第三个例证彰显了创设表之间的关联。在本节中央银行使C#代码成立数据库而未有动用SQL
DDL语句(或通过选取设计器卡塔 尔(阿拉伯语:قطر‎创立数据库。 

示范应用程序MenusSample使用以下正视项和命名空间:

  依赖项

NETStandard.Library
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer

  命名空间

Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.ChangeTracking
System
System.Collections.Generic
System.ComponentModel.DataAnnotations
System.ComponentModel.DataAnnotations.Schema
System.Linq
System.Threading
System.Threading.Tasks
static System.Console

HiLo是在NHibernate中生成主键的生龙活虎种方法,不过现在大家得以在Entity
Framework Core中应用。所以在这里篇内容中,笔者将向你在介绍怎样在Entity
Framework Core中选择HiLo生成主键。

Fluent API  

影响创设的表的另生机勃勃种办法是利用Fluent
API中DbContext派生类的OnModelCreating方法。它的优点是能够维持实体类型大致,而不增添任何性质,Fluent
API还提供了比使用品质更加多的选项。 

以下代码片段突显了BooksContext类重写OnModelCreating方法。作为参数选拔的ModelBuilder类提供了部分主意,并定义了两种增添方法。
HasDefaultSchema是中间二个增添方法,它将默许结构接收于当下具有项目标模子。
Entity方法再次来到多少个EntityTypeBuilder,令你能够自定义实体,举个例子将其映射到一定的表名和定义键和目录(代码文件MenusSample
/ MenusContext.cs卡塔 尔(英语:State of Qatar):

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  base.OnModelCreating(modelBuilder);

  modelBuilder.HasDefaultSchema("mc");

  modelBuilder.Entity<MenuCard>()
    .ToTable("MenuCards")
    .HasKey(c => c.MenuCardId);

  // etc.

  modelBuilder.Entity<Menu>()
    .ToTable("Menus")
    .HasKey(m => m.MenuId);

  // etc.
}

EntityTypeBuilder定义了二个Property方法来计划属性。
Property方法再次来到PropertyBuilder,能够依次配置具备最大尺寸值,必要的装置和SQL类型的品质,并点名是还是不是应自动生成值(比如标志列卡塔 尔(英语:State of Qatar):

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  // etc.

  modelBuilder.Entity<MenuCard>()
    .Property<int>(c => c.MenuCardId)
    .ValueGeneratedOnAdd();

  modelBuilder.Entity<MenuCard>()
    .Property<string>(c => c.Title)
    .HasMaxLength(50);

  modelBuilder.Entity<Menu>()
    .Property<int>(m => m.MenuId)
    .ValueGeneratedOnAdd();

  modelBuilder.Entity<Menu>()
.Property<string>(m => m.Text)
    .HasMaxLength(120);

  modelBuilder.Entity<Menu>()
    .Property<decimal>(m => m.Price)
    .HasColumnType("Money");

  // etc.
} 

EntityTypeBuilder定义映射方法去定义豆蔻年华对多映射。HasMany
结合 WithOne 方法定义了多Menus 和五个Menu Card 的璀璨。
HasMany供给予WithOne链接,即HasOne方法必要多个带WithMany或WithOne的链。链接
HasOne 和
WithMany定义了生机勃勃对多关系,链接HasOne与WithOne定义了意气风发对生龙活虎的涉及:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  // etc.

  modelBuilder.Entity<MenuCard>()
    .HasMany(c => c.Menus)
    .WithOne(m => m.MenuCard);
  modelBuilder.Entity<Menu>()
    .HasOne(m => m.MenuCard)
    .WithMany(c => c.Menus)
    .HasForeignKey(m => m.MenuCardId);
}

在OnModelCreating方法中开创映射之后方可制造如前所示的迁徙。

什么是Hilo?

HiLo是High Low的简写,翻译成汉语叫高低位形式。

HiLo是由“Hi”和“Lo”两局部生成主键的意气风发种格局。“Hi”部分出自数据库,“Lo”部分在内部存款和储蓄器中生成以创设唯黄金年代值。请记住,“Lo”是四个限量数字,如0-100。因而,当“Hi”部分用完“Lo”范围时,再度举行数据库调用以获得下叁个“Hi数字”。因而HiLo形式的亮点在于你事先能够精通主键的值,而不用每一次都与数库据爆发相互

总括有以下四点:

  1. “Hi”部分由数据库分配,五个冒出需要保管收获唯大器晚成的总是值;
  2. 假若获得“Hi”部分,大家还亟需精晓“incrementSize”的值(“Lo”条约标多少卡塔 尔(英语:State of Qatar);
    “Lo”取的范围:[0,incrementSize];
  3. 标记范围的公式是:(Hi – 1) * incrementSize) + 1(Hi –
    1) * incrementSize) + incrementSize)
  4. 当全体“Lo”值使用完时,要求再行从数据库中抽出五个新的“Hi”值,并将“Lo”部分重新设置为0。

在那间演示在三个冒出事务中的例子,每种业务插入三个实体:

图片 4

更新记录

只需更动已加载上下文的对象并调用SaveChangesAsync就可以轻易达成立异记录(代码文件BooksSample
/ Program.cs卡塔尔国:

private async Task UpdateBookAsync()
{
  using (var context = new BooksContext())
  {
    int records = 0;
    var book = context.Books.Where(b => b.Title =="Professional C# 6")
      .FirstOrDefault();
    if (book != null)
    {
      book.Title ="Professional C# 6 and .NET Core 5";
      records = await context.SaveChangesAsync();
    }
    WriteLine($"{records} record updated");
  }
  WriteLine();
}

选用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部分卡塔尔国系列值。

写入数据库

于今已开立了有Books表的数据库,也定义了模型和左右文类,然后能够用多少填充表。创设AddBookAsync方法将Book对象增添到数据库。首先,BooksContext对象被实例化,这里运用using语句确认保证数据库连接关闭。使用Add方法将目的增加到上下文之后,实体被写入调用SaveChangesAsync的数据库(代码文件BooksSample
/ Program.cs卡塔 尔(阿拉伯语:قطر‎:

private async Task AddBookAsync(string title, string publisher)
{
  using (var context = new BooksContext())
  {
    var book = new Book
    {
      Title = title,
      Publisher = publisher
    };
    context.Add(book);
    int records = await context.SaveChangesAsync();

    WriteLine($"{records} record added");
  }
  WriteLine();
} 

要增加书籍列表,能够接收AddRange方法(代码文件Books萨姆ple
/ Program.cs卡塔尔:

private async Task AddBooksAsync()
{
  using (var context = new BooksContext())
  {
    var b1 = new Book
    {
      Title ="Professional C# 5 and .NET 4.5.1",
      Publisher ="Wrox Press"
    };
    var b2 = new Book
    {
      Title ="Professional C# 2012 and .NET 4.5",
      Publisher ="Wrox Press"
    };
    var b3 = new Book
    {
      Title ="JavaScript for Kids",
      Publisher ="Wrox Press"
    };
    var b4 = new Book
    {
      Title ="Web Design with HTML and CSS",
      Publisher ="For Dummies"
    };
    context.AddRange(b1, b2, b3, b4);
    int records = await context.SaveChangesAsync();
    WriteLine($"{records} records added");
  }
  WriteLine();
} 

 运维应用程序并调用那几个点子后,可以使用SQL
Server对象财富微处理机查看写入到数据库的多少。

从数据库读取

从C#代码读取数据只须要调用BooksContext并访谈Books属性。访谈此属性会创设三个SQL语句从数据库中搜索全数书籍(代码文件Books萨姆ple
/ Program.cs卡塔 尔(英语:State of Qatar):

private void ReadBooks()
{
  using (var context = new BooksContext())
  {
    var books = context.Books;
    foreach (var b in books)
    {
      WriteLine($"{b.Title} {b.Publisher}");
    }
  }
  WriteLine();
}

在调解时期展开AMDliTrace 伊芙nts窗口,能够看出发送到数据库的SQL语句(须要Visual
Studio 公司版卡塔 尔(阿拉伯语:قطر‎:

SELECT [b].[BookId], [b].[Publisher], [b].[Title]
FROM [Books] AS [b]

Framework提供了多个LINQ提供程序,能够成立LINQ查询访谈数据库。能够利用如下所示语法的点子:

private void QueryBooks()
{
  using (var context = new BooksContext())
  {
    var wroxBooks = context.Books.Where(b => b.Publisher =="Wrox Press");
    foreach (var b in wroxBooks)
    {
      WriteLine($"{b.Title} {b.Publisher}");
    }
  }
  WriteLine();
}

或选取LINQ查询语法:

var wroxBooks = from b in context.Books
                where b.Publisher =="Wrox Press"
                select b;

选取那三种不一致的语法,都将发送下边包车型客车SQL语句到数据库:

SELECT [b].[BookId], [b].[Publisher], [b].[Title]
FROM [Books] AS [b]
WHERE [b].[Publisher] = 'Wrox Press'

*注意 在第13章“语言集成查询”中详细座谈了LINQ。
*

使用.NET CLI实行搬迁

要动用C#代码自动创设数据库,可以采取enet工具使用package
dotnet-ef扩张.NET
CLI工具。此软件公文包含用于为搬迁创制C#代码的吩咐。通过设置dotnet-ef
NuGet包可以职责令可用。您能够透过从品类布局文件(代码文件Menus萨姆ple /
project.json卡塔 尔(英语:State of Qatar)中的工具部分引用此软件包来安装它:

"tools": {
  "dotnet-ef":"1.0.0-*"
 }

ef命令提供以下命令:数据库、dbcontext和迁移。数据库命令用于将数据库晋级到一定的迁徙境况。
dbcontext命令列出项目中的全数DbContext派生类型(dbcontext
list卡塔 尔(阿拉伯语:قطر‎,并从数据库(dbcontext scaffold卡塔 尔(英语:State of Qatar)创造上下文和实业。
migrations命令则创立和删除迁移,以致开创SQL脚本去创制包罗全体迁移的数据库。假如生产数据库只可以从SQL助理馆员使用SQL代码创制和改过,能够将扭转的本子移交给SQL助理馆员。 

为了创立起来迁移以从代码成立数据库,能够从开辟人士命令提醒符调用以下命令,该命令创造名称叫InitMenuCards的动员搬迁:

>dotnet ef migrations add InitMenuCards

指令migrations
add使用反射以至相反的援引模型访问DbContext派生类。此音讯成立八个类来成立和翻新数据库。使用Menu,MenuCard和MenusContext类创制三个类,MenusContextModelSnapshot和InitMenuCards。命令成功后方可在Migrations文件夹中找到那三种等级次序。

MenusContextModelSnapshot类富含构建数据库的模子的当下情状:

[DbContext(typeof(MenusContext))]
partial class MenusContextModelSnapshot: ModelSnapshot
{
  protected override void BuildModel(ModelBuilder modelBuilder)
  {
    modelBuilder
     .HasAnnotation("ProductVersion","7.0.0-rc1-16348")
     .HasAnnotation("SqlServer:ValueGenerationStrategy",
       SqlServerValueGenerationStrategy.IdentityColumn);

     modelBuilder.Entity("MenusSample.Menu", b =>
     {
       b.Property<int>("MenuId")
        .ValueGeneratedOnAdd();
       b.Property<int>("MenuCardId");
       b.Property<decimal>("Price");
       b.Property<string>("Text");
       b.HasKey("MenuId");
     });

     modelBuilder.Entity("MenusSample.MenuCard", b =>
     {
       b.Property<int>("MenuCardId")
        .ValueGeneratedOnAdd();

       b.Property<string>("Title");
       b.HasKey("MenuCardId");
     });
     modelBuilder.Entity("MenusSample.Menu", b =>
     {
       b.HasOne("MenusSample.MenuCard")
        .WithMany()
        .HasForeignKey("MenuCardId");
     });
  }
}

InitMenuCards类定义了Up和Down方法。
Up方法列出了创设MenuCard和菜单表所需的有所操作,包涵主键、列和涉嫌。
Down方法删除多少个表:

public partial class InitMenuCards: Migration
{
  protected override void Up(MigrationBuilder migrationBuilder)
  {
    migrationBuilder.CreateTable(
      name:"MenuCard",
      columns: table => new
      {
        MenuCardId = table.Column<int>(nullable: false)
          .Annotation("SqlServer:ValueGenerationStrategy",
            SqlServerValueGenerationStrategy.IdentityColumn),
        Title = table.Column<string>(nullable: true)
      },
      constraints: table =>
      {
        table.PrimaryKey("PK_MenuCard", x => x.MenuCardId);
      });

    migrationBuilder.CreateTable(
      name:"Menu",
      columns: table => new
      {
        MenuId = table.Column<int>(nullable: false)
          .Annotation("SqlServer:ValueGenerationStrategy",
            SqlServerValueGenerationStrategy.IdentityColumn),
        MenuCardId = table.Column<int>(nullable: false),
        Price = table.Column<decimal>(nullable: false),
        Text = table.Column<string>(nullable: true)
      },
      constraints: table =>
      {
        table.PrimaryKey("PK_Menu", x => x.MenuId);
        table.ForeignKey(
          name:"FK_Menu_MenuCard_MenuCardId",
          column: x => x.MenuCardId,
          principalTable:"MenuCard",
          principalColumn:"MenuCardId",
          onDelete: ReferentialAction.Cascade);
      });
  }

  protected override void Down(MigrationBuilder migrationBuilder)
  {
    migrationBuilder.DropTable("Menu");
    migrationBuilder.DropTable("MenuCard");
  }
}

注意 正在张开的各样更正都能够创建另三个搬迁。新搬迁仅定义从先前版本到新本子所需的更换。若是顾客的数据库须要从随机前期的版本更新,迁移数据库时调用供给的动员搬迁。 

在开采进度中,也行无需具有的迁徙,可能要求从品种中创设,因为恐怕未有该类不常气象的数据仓库储存在。在此种状态下得以去除迁移并成立一个一点都不小的新搬迁。

选取MSBuild进行搬迁  

假若你正在使用基于MSBuild的项目Entity
Framework迁移实际不是DNX,迁移命令是莫衷一是的。使用完全框架调节台应用程序、WPF应用程序或ASP.NET
4.6品类别别,要求在NuGet包微电脑调节新北钦点迁移命令,并非开拓人士命令提醒符。从Visual
Studio通过 工具➪库微型机调节台➪包微处理机控制台
运行包微机调节台。

在包微型机调节台能够行使PowerShell脚本增添和删除迁移。命令如下

> Add-Migration InitMenuCards

制造叁个Migrations文件夹,在那之中包蕴如前所示的迁移类。

成立数据库 

趁着迁移类型形成,能够成立数据库。
DbContext派生类MenusContext包括一个回来DatabaseFacade对象的Database属性。使用DatabaseFacade可以创造和删除数据库。借使数据库不设有,EnsureCreated方法会成立数据库;如若数据库已存在,则不进行此外操作。方法EnsureDeletedAsync删除数据库。以下代码片段创制数据库(假设它不设有卡塔尔(代码文件Menus萨姆ple
/ Program.cs卡塔尔:

private static async Task CreateDatabaseAsync()
{
  using (var context = new MenusContext())
  {
bool created = await context.Database.EnsureCreatedAsync();
    string createdText = created ?"created":"already exists";
    WriteLine($"database {createdText}");
  }
}

注意 设若数据仓库储存在可是几个较旧的结构版本,EnsureCreatedAsync方法不会动用结构改动。那个时候能够透过调用Migrate方法来扩充组织晋级。
Migrate是Microsoft.Data.Entity命名空间中定义的DatabaseFacade类的增加方法。

运路程序将创制表MenuCard和Menu。基于暗中认可约定,表与实体类型是同等的名称。另二个预订用于创立主键:MenuCardId列会被定义为主键,因为属性名以Id截止。

CREATE TABLE [dbo].[MenuCard] (
  [MenuCardId] INT            IDENTITY (1, 1) NOT NULL,
  [Title]      NVARCHAR (MAX) NULL,
  CONSTRAINT [PK_MenuCard] PRIMARY KEY CLUSTERED ([MenuCardId] ASC)
);

Menu表定义了MenuCardId,它是MenuCard表的外键。由于DELETE
CASCADE,删除MenuCard也会去除全体关乎的Menu行:

CREATE TABLE [dbo].[Menu] (
  [MenuId]     INT             IDENTITY (1, 1) NOT NULL,
  [MenuCardId] INT             NOT NULL,
  [Price]      DECIMAL (18, 2) NOT NULL,
  [Text]       NVARCHAR (MAX)  NULL,
  CONSTRAINT [PK_Menu] PRIMARY KEY CLUSTERED ([MenuId] ASC),
  CONSTRAINT [FK_Menu_MenuCard_MenuCardId] FOREIGN KEY ([MenuCardId])
  REFERENCES [dbo].[MenuCard] ([MenuCardId]) ON DELETE CASCADE
);

在开立代码中有部分部分退换是立见成效的。例如,Text
和 Title 列的高低能够从NVARCHA传祺(MAX卡塔尔减小,SQL
Server定义了可用于Price列的Money类型,何况协会名称能够从dbo改良。 Entity
Framework提供了七个选拔从代码中实行那几个退换:数据阐明和Fluent
API,上边将钻探。

数据申明

耳熟能详生成的数据库的意气风发种方式是向实体类型丰硕数据注释。能够使用Table属性改进表的称号。要改变结构名称,Table属性定义Schema属性。假设要为字符串类型钦点分化的长短,能够接收马克斯Length属性(代码文件MenusWithDataAnnotations
/ Menu卡德.cs卡塔尔国:

[Table("MenuCards", Schema ="mc")]
public class MenuCard
{
  public int MenuCardId { get; set; }
  [MaxLength(120)]
  public string Title { get; set; }
  public List<Menu> Menus { get; }
}

Menu类的Table和马克斯Length属性同样能够使用。使用Column属性纠正SQL类型(代码文件MenusWithDataAnnotations
/ Menu.cs卡塔尔:

[Table("Menus", Schema ="mc")]
public class Menu
{
  public int MenuId { get; set; }
  [MaxLength(50)]
  public string Text { get; set; }
  [Column(TypeName ="Money")]
  public decimal Price { get; set; }
  public int MenuCardId { get; set; }
  public MenuCard MenuCard { get; set; }
}

运用迁移创立数据库后能够见到结构名称下表的新名称,以致Title、Text
和 Price 字段中已更正的数据类型:

CREATE TABLE [mc].[MenuCards] (
  [MenuCardId] INT            IDENTITY (1, 1) NOT NULL,
  [Title]      NVARCHAR (120) NULL,
  CONSTRAINT [PK_MenuCard] PRIMARY KEY CLUSTERED ([MenuCardId] ASC)
);

CREATE TABLE [mc].[Menus] (
  [MenuId]     INT           IDENTITY (1, 1) NOT NULL,
  [MenuCardId] INT           NOT NULL,
  [Price]      MONEY         NOT NULL,
  [Text]       NVARCHAR (50) NULL,
  CONSTRAINT [PK_Menu] PRIMARY KEY CLUSTERED ([MenuId] ASC),
  CONSTRAINT [FK_Menu_MenuCard_MenuCardId] FOREIGN KEY ([MenuCardId])
    REFERENCES [mc].[MenuCards] ([MenuCardId]) ON DELETE CASCADE
);

实业框架简要介绍

首先个示范使用单个Book类型,并将此类型映射到SQL
Server数据库中的Books表。能够将记录写入数据库,然后读取,更新和删除它们。 

在第一个示范中,首先创造数据库。能够运用Visual
Studio 二〇一四中的SQL
Server对象能源微型机推行此操作。选择数据库实例(与Visual
Studio一齐安装的(localdb卡塔 尔(英语:State of Qatar)\
MSSQLLocalDB卡塔尔国,单击树视图中的数据库节点,然后选拔“增加新数据库”。示例数据库只有一个名称为Books的表。 

筛选Books数据库中的表节点,然后选取”增加新表”来创设表Books。使用图38.第11中学所示的设计器,可能通过在T-SQL编辑器中输入SQL
DDL语句,都能够创造表Books。以下代码段显示了用于创建表的T-SQL代码。单击“更新”开关能够将改成提交到数据库。

CREATE TABLE [dbo].[Books]
(
  [BookId] INT NOT NULL PRIMARY KEY IDENTITY,
  [Title] NVARCHAR(50) NOT NULL,
  [Publisher] NVARCHAR(25) NOT NULL
)

实体框架的历史

实体框架是提供实体到事关的投射的框架。通过这种办法,能够创设映射到多少库表的项目,使用LINQ创造数据库查询,创设和换代目的,并将它们写入数据库。 

因而日久天长对Entity
Framework的为数非常的少改善,最新的版本是贰个一心的重写。一齐来拜访Entity
Framework的野史,以至重写的原故。

  • Entity
    Framework 1
    —Entity Framework的第七个版本未有思考好与.NET
    3.5同盟,但它比一点也不慢就能够与.NET 3.5 SP1宽容。另一个产品LINQ to
    SQL提供了生机勃勃部分接近的成效,且已经可用于.NET 3.5。 LINQ to SQL和Entity
    Framework在非常的大程度上提供了近乎的效率。LINQ to
    SQL更便于使用,但只好用于访谈SQL
    Server。实体框架是遵照提供程序的,并提供了对两样关周到据库的会见。它包涵更加多的效力,比方多对多映射而没有必要映射对象,n对n映射是恐怕的。
    Entity
    Framework的叁个破绽是它的模子类型必要由EntityObject基类派生。将目的映射到关系接纳带有XML的EDMX文件实现的。蕴含的XML由八个形式组成:概念形式定义(CSD卡塔尔国定义具备其属性和事关的目的类型;存款和储蓄方式定义(SSD卡塔 尔(阿拉伯语:قطر‎定义数据库表、列和涉及;以致映射情势语言(MSL卡塔尔定义CSD和SSD怎么样互相映射。

  • Entity
    Framework 4
    —Entity Framework 4 在.NET
    4中极度,并且赢得了重大校勘,当中大多起点LINQ到SQL的主见。由于变化十分大,版本2和3已被跳过。那么些版本里增添了推迟加载以获得访谈属性的涉嫌。在采用SQL数据定义语言(DDL卡塔尔国设计模型之后,能够创制数据库。未来选取Entity
    Framework的多少个模型是Database First或Model
    First。可能最要害的表征是扶植轻巧对象类(POCO卡塔 尔(阿拉伯语:قطر‎,由此不再供给从基类EntityObject派生。

乘胜更新(举个例子Entity
Framework 4.1,4.2卡塔尔,NuGet包扩展了附加的效应,因而能更加快地增加效果。
Entity Framework 4.1提供了Code
First模型,在那之中用于定义映射的EDMX文件不再采纳。相反,全体的照射都使用C#代码定义

  • 应用品质或Fluent API来定义的照耀。

Entity Framework
4.3充实了对搬迁的扶助。有了那一点,就足以选用C#代码定义数据库结构的改进。使用数据库从应用程序自动应用数据库更新。

  • Entity
    Framework 5
    —Entity Framework 5的NuGet包援助.NET 4.5和.NET
    4应用程序。可是,Entity Framework 5的好多效应都可用于.NET 4.5。
    Entity Framework依旧基于.NET
    4.5在系统上设置的项目。此版本的新扩张效益是性质修改以至扶持新的SQL
    Server作用,比如空间数据类型。

  • Entity
    Framework 6
    —Entity Framework 6解决了Entity Framework
    5的一些标题,此中有的是安装在系统上的框架的一片段,风度翩翩部分透过NuGet扩充提供。近来Entity
    Framework的满贯代码已移至NuGet包。为了不造成冲突,使用了三个新的命名空间。将应用程序移植到新本羊时,必得退换命名空间。

本书切磋Entity
Framework的风尚版本,Entity Framework Core
1.0。此版本是二个去除旧的一言一行周到重写,不再补助CSDL,SSDL和MSL的XML文件映射,只帮忙Code
First – 使用Entity Framework 4.1抬高的模型。Code First
并不意味数据库不可能先存在。您能够先创立数据库,可能仅从代码中定义数据库,以上二种选择都是立见成效的。

注意 Code First
这些称号某个程度上令人误会。Code First
先成立代码或先数据库都是行之有效的。最早Code First的测量试验版本名称是Code
Only。因为其余模型选项在名称中有First,所以“Code
Only”的名目也被改换。

Entity
Framework 的应有尽有重写不仅仅扶植关周详据库,还援助NoSql数据库 –
只供给八个提供程序。在作文本文时,提供程序接济有限,但相信会随即间而扩展。 

新本子的Entity
Framework基于.NET
Core,因此在Linux和Mac系统上也能够采取此框架。 

Entity
Framework Core 1.0不完全援救Entity Framework
6提供的装有功能。随着年华的延期,Entity
Framework的新本子将提供越来越多效果与利益,在乎所采用的Entity
Framework的版本。固然接收Entity Framework 6
相当多有力的说辞,但在非Windows平台上选取ASP.NET Core 1.0、Entity
Framework和通用Windows平台(UWP),以至非关周密据存款和储蓄,都亟待运用Entity
Framework Core 1.0。 

本章介绍Entity
Framework Core 1.0。从三个简便的模型读取和SQL
Server中写入音信开始,稍后会介绍加多关系,在写入数据库时将介绍校正追踪器和冲突管理。利用搬迁成立和退换数据库结构是本章的另三个要害部分。 

注意 本章使用Books数据库,此数据库包罗在示范代码的下载包中 www.wrox.com/go/professionalcsharp6

创办模型 

用以访谈Books数据库的示范应用程序BookSample是一个调整台应用程序(Package卡塔尔。此示例使用以下依赖项和命名空间:

  依赖项

NETStandard.Library
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer

   取名空间

Microsoft.EntityFrameworkCore
System.ComponentModel.DataAnnotations.Schema
System
System.Linq
System.Threading.Tasks
static System.Console

 图片 8


38.1
  

Book类是二个粗略的实业类型,它定义了四本特性。
BookId属性映射到表的主键,Title属性指向标题列,Publisher属性指向Publisher列。Table属性应用于类型将项目映射到Books表(代码文件BooksSample
/ Book.cs卡塔尔国:

[Table("Books")]
public class Book
{
  public int BookId { get; set; }
  public string Title { get; set; }
  public string Publisher { get; set; }
}

始建关系

让大家最初创设七个模子。示例项目采取MenuCard和Menu类型定义意气风发对多涉及。MenuCard包涵Menu对象的列表。这种关系由List
<Menu>类型的Menu属性轻便定义(代码文件MenusSample /
MenuCard.cs卡塔尔国:

public class MenuCard
{
  public int MenuCardId { get; set; }
  public string Title { get; set; }
  public List<Menu> Menus { get; } = new List<Menu>();

  public override string ToString() => Title;
}

该关系也得以从另叁个角度访谈,菜单能够动用MenuCard属性访谈MenuCard。钦命MenuCardId 属性去定义外键关系(代码文件MenusSample / Menu.cs卡塔 尔(英语:State of Qatar):

public class Menu
{
  public int MenuId { get; set; }
  public string Text { get; set; }
  public decimal Price { get; set; }

  public int MenuCardId { get; set; }
  public MenuCard MenuCard { get; set; }

  public override string ToString() => Text;
}

到数据库的投射由MenusContext类完成。那么些类定义为与上贰个内外文类型相近的品种,它只含有四个属性来映射两个对象类型:属性Menus和MenuCards(代码文件Menus萨姆ples
/ MenusContext.cs卡塔尔国:

public class MenusContext: DbContext
{
  private const string ConnectionString = @"server=(localdb)\MSSQLLocalDb;" +     "Database=MenuCards;Trusted_Connection=True";
  public DbSet<Menu> Menus { get; set; }
  public DbSet<MenuCard> MenuCards { get; set; }

  protected override void OnConfiguring(DbContextOptionsBuilder  optionsBuilder)
  {
    base.OnConfiguring(optionsBuilder);
    optionsBuilder.UseSqlServer(ConnectionString);
  }
}

**译文,村办原创,转发请表明出处(C# 6 与 .NET Core 1.0 高档编制程序 – 38 章 实体框架核心(上)卡塔 尔(阿拉伯语:قطر‎,不对的地点接待提议与交换。** 

章节出自《Professional
C# 6 and .NET Core
1.0》。水平有限,各位阅读时精心甄别,唯望莫误人子弟。

附英语版最早的作品:Professional C# 6 and .NET Core 1.0 – 38 Entity
Framework
Core

本章节译文分为上下篇,下篇见: C# 6 与 .NET Core 1.0 高等编制程序 – 38 章
实体框架核心(下)


本章内容

  • Entity
    Framework Core 1.0简介
  • 选拔注重注入实体框架
  • 创制关系模型
  • 使用.NET
    CLI工具和MSBuild举行搬迁
  • 对象追踪
  • 履新指标和对象树
  • 冲突管理与更新
  • 使用工作

Wrox.Com关于本章的源代码下载

本章的wrox.com代码下载位于
www.wrox.com/go/professionalcsharp6
下载代码选项卡。本章的代码首要有以下示例:

  • Books
    Sample
  • Books
    Sample with DI
  • Menus
    Sample
  • Menus
    with Data Annotations
  • Conflict
    Handling Sample
  • Transactions
    Sample 

使用依赖注入  

Entity
Framework Core 1.0放到了对信任注入的扶持。连接和SQL
Server选取能够经过行使信赖注入框架注入,而非定义和接下来使用DbContext派生类的SQL
Server连接。 

要翻开此操作,BooksSampleWithDI示例项目对上二个代码示例项目展开了改换。 

此示例使用以下信赖项和命名空间:

  依赖项

NETStandard.Library
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.Framework.DependencyInjection 

  命名空间

Microsoft.EntityFrameworkCore
System.Linq
System.Threading.Tasks
static System.Console

BooksContext类现在看起来很简短,只需定义Books属性(代码文件BooksSampleWithDI
/ BooksContext.cs卡塔 尔(阿拉伯语:قطر‎:

public class BooksContext: DbContext
{
  public DbSet<Book> Books { get; set; }
}

BooksService是接收BooksContext的新类。BooksContext通过注入构造函数注入。方法AddBooksAsync和ReadBooks与上一个示范中的那些艺术十二分相符,但他俩选用BooksService类的上下文成员,实际不是创建四个新的(代码文件Books萨姆pleWithDI
/ BooksService.cs卡塔尔国:

public class BooksService
{
  private readonly BooksContext _booksContext;
  public BooksService(BooksContext context)
  {
    _booksContext = context;
  }

  public async Task AddBooksAsync()
  {
    var b1 = new Book
    {
      Title ="Professional C# 5 and .NET 4.5.1",
      Publisher ="Wrox Press"
    };
    var b2 = new Book
    {
      Title ="Professional C# 2012 and .NET 4.5",
      Publisher ="Wrox Press"
    };
    var b3 = new Book
    {
      Title ="JavaScript for Kids",
      Publisher ="Wrox Press"
    };
    var b4 = new Book
    {
      Title ="Web Design with HTML and CSS",
      Publisher ="For Dummies"
    };
    _booksContext.AddRange(b1, b2, b3, b4);
    int records = await _booksContext.SaveChangesAsync();

    WriteLine($"{records} records added");
  }

  public void ReadBooks()
  {
    var books = _booksContext.Books;
    foreach (var b in books)
    {
      WriteLine($"{b.Title} {b.Publisher}");
    }
    WriteLine();
  }
} 

依赖注入框架的器皿在
InitializeServices
方法中开首化。成立一个ServiceCollection实例,将BooksService类增加到此聚众中,并张开临时生命周期管理。那样,每便诉求该服务时都会实例化
ServiceCollection。对于注册Entity Framework和SQL
Server,能够用扩张方法AddEntityFramework,AddSqlServer和AddDbContext。
AddDbContext方法供给二个Action委托作为参数,此中选拔到四个DbContextOptionsBuilder参数。有了该选项参数,能够利用UseSqlServer扩充方法配置上下文。这里用Entity
Framework注册SQL
Server与上三个示范是近乎的职能(代码文件BooksSampleWithDI /
Program.cs卡塔 尔(阿拉伯语:قطر‎:

private void InitializeServices()
{
  const string ConnectionString =@"server= (localdb)\MSSQLLocalDb;database=Books;trusted_connection=true";
  var services = new ServiceCollection();
  services.AddTransient<BooksService>();
  services.AddEntityFramework()
    .AddSqlServer()
    .AddDbContext<BooksContext>(options =>
      options.UseSqlServer(ConnectionString));
  Container = services.BuildServiceProvider();
}

public IServiceProvider Container { get; private set; }

劳动的开端化以至BooksService的选择是从Main方法成功的。通过调用IServiceProvider的GetService方法来查究BooksService(代码文件BooksSampleWithDI
/ Program.cs卡塔尔国:

static void Main()
{
  var p = new Program();
  p.InitializeServices();

  var service = p.Container.GetService<BooksService>();
  service.AddBooksAsync().Wait();
  service.ReadBooks();
}

运作应用程序能够观察记录已增添到图书数据库中然后从中读取记录。

*注意
在第31章“XAML应用程序的形式”中阅读有关重视注入和Microsoft.Framework.DependencyInjection包的越来越多新闻,还足以参见第40章“ASP.NET
Core”和第41章“ ASP.NET MVC“。*

从数据库成立模型  

从模型能够创建数据库,相反从数据库也得以创立模型。 

要从SQL
Server数据库施行此操作,除了其余包,还非得将NuGet包增多到DNX项目中,EntityFramework.MicrosoftSqlServer.Design。然后能够在开垦职员命令提醒符使用以下命令:

> dnx ef dbcontext scaffold 
"server=(localdb)\MSSQLLocalDb;database=SampleDatabase; trusted_connection=true""EntityFramework.MicrosoftSqlServer"

dbcontext命令能够从项目中列出DbContext对象,同一时候也开创DBContext对象。命令scaffold创建DbContext派生类以至模型类。
dnx ef dbcontext scaffold
要求多少个必备的参数:数据库的接连字符串和平运动用的提供程序。前面所示的言辞中,在SQL
Server(localdb卡塔尔\
MSSQLLocalDb上访谈数据库SampleDatabase。使用的提供程序是EntityFramework.MicrosoftSqlServer。那个NuGet包以致独具相同名称和规划后缀的NuGet包必须增添到项目中。 

运作此命令后,能够观望DbContext派生类以至改换的模子类型。暗许情形下,模型的配备使用fluent
API完结。不过也得以将其变动为运用提供-a选项的数额教学。仍然是能够影响生成的前后文类名称以至出口目录。只需选择接纳-h检查不相同的可用选项。

 

—————-未完待续

相关文章