HiLo是在NHibernate中生成主键的一种方法,但是现在大家得以在Entity
Framework Core中应用。所以在那篇内容中,我将向你在介绍怎么样在Entity
Framework Core中采取HiLo生成主键。

前言

Contoso 大学示范 Web 应用程序演示如何运用实体框架(EF)Core 2.0 和
Visual Studio 2017 创制 ASP.NET Core 2.0 MVC Web 应用程序。
演示应用程序是杜撰的Contoso高校的网站。
它概括学生入学,课程成立和先生职务等作用。
那是一多重教程中的第一章,介绍怎么着开始营造Contoso高校示例应用程序。
下载或查看已做到的应用程序 –
官方

本系列小说翻译索引目录

EF Core 2.0 是EF的风尚版本,但还未曾包含所有的 EF 6.x 成效。 有关 EF 6.x
和 EF Core 之间什么选取的音信,请参阅 EF Core vs.
EF6.x

借使您选拔 EF 6.x
,请参阅本课程连串的先前版本

注意事项

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

在那边演示在四个冒出事务中的例子,每个工作插入多少个实体:

365bet体育投注 1

支付环境

设置如下工具:

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

至于体系越多的始末,可以查看如下材料:

故障排除

设若赶上难点,您不可以化解,常常可以通过将代码与成就的品类进展相比较来找到解决方案。
有关常见错误和化解方法的列表,请参阅本连串最后一个学科的故障排除部分。
若是你没有找到所需的情节,您也足以在 StackOverflow.com 上发问。

小贴士

本体系包蕴10个科目,每个教程都创设在中期教程中的基础之上。
在成功做到每个教程之后,请考虑保存项目标副本。
然后,假使碰着难题,您可以从上一个科目重新起始,无需从头开首。

行使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序列。

365bet体育投注 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来阐明它。
365bet体育投注 3

次调用dataContext.SaveChanges()时,3个Category实体将被保存。查看执行的SQL语句。主键值已经被转移,种类值的收获也只举行了三遍。
365bet体育投注 4

尽管插入3个Product实业,连串值也不会从数据库中赢得。唯有当插入10条记下(Lo部分耗尽)时,才会向数据库调用得到下一个(Hi部分)种类值。

Contoso 大学网站利用

课程中打造的是一个简短的高校网站。
用户可以查看和换代学生,课程和教育者新闻。 上面是你将要创立的部分页面。

365bet体育投注 5

index

365bet体育投注 6

edit

网站的 UI 风格与内置模板生成的 UI 风格保持一致,本学科主要关怀怎样利用
Entity Framework。

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

365bet体育投注 7

始建 ASP.NET Core MVC 网站应用

打开 Visual Studio 并创制名为 “ContosoUniversity” 的新 ASP.NET Core C#
web 项目。

  • 从文件菜单中,选用新建>项目。
  • 从左窗格中选用 已设置 -> Visual C# -> Web 。
  • 中间窗格接纳 ASP.NET Core Web 应用程序。
  • 输入 ContosoUniversity 作为项目名称,然后单击确定。
![](https://upload-images.jianshu.io/upload_images/4235187-1c7a131da4c70365.png)

newProject
  • 等待 “新建 ASP.NET Core Web 应用程序” 对话框出现
  • 挑选 ASP.NET Core 2.0 和 Web应用程序(模型视图控制器)模板。
  • 留意:本学科要求 ASP.NET Core 2.0 和 EF Core 2.0 或更高版本 –
    确保未选用ASP.NET Core 1.1。
  • 担保认证设置为“不举行身份验证”。
  • 单击 “确定” 按钮。

365bet体育投注 8

newCore

配置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先河。

365bet体育投注 9

再就是由于IncrementBy慎选设置为“5”,所以当在上下文中添加第6个插入时,将展开数据库调用以赢得下一个种类值。以下是插入3个Category实业然后插入3个的Product实业时SQL
Server
profiler的显示屏截图,您可以看到数据库调用获取连串的下一个值的次数是2次。
365bet体育投注 10

一旦你对在Entity Framework
Core中运用HiLo生成主键感兴趣,不防自己入手测试一下。

参考资料:

安装网站样式

概括修改多少个岗位,设置站点菜单,布局和主页。
打开 Views/Shared/_Layout.cshtml 文件,进行以下改变:

  • 将三处 “ContosoUniversity” 文字修改为“Contoso University”。
  • 添加 学生、课程、助教和部门菜单,删除联系人菜单。

第一的改动如下

<html>
......
    <title>@ViewData["Title"] - Contoso University</title>
......
                class="navbar-brand">Contoso University</a>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
                    <li><a asp-area="" asp-controller="Students" asp-action="Index">Students</a></li>
                    <li><a asp-area="" asp-controller="Courses" asp-action="Index">Courses</a></li>
                    <li><a asp-area="" asp-controller="Instructors" asp-action="Index">Instructors</a></li>
                    <li><a asp-area="" asp-controller="Departments" asp-action="Index">Departments</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>© 2017 - Contoso University</p>
        </footer>
    </div>
</body>
</html>

在 Views/Home/Index.cshtml 文件,使用以下代码替换文件的内容:

@{
    ViewData["Title"] = "Home Page";
}

<div class="jumbotron">
    <h1>Contoso University</h1>
</div>
<div class="row">
    <div class="col-md-4">
        <h2>Welcome to Contoso University</h2>
        <p>
            Contoso University is a sample application that
            demonstrates how to use Entity Framework Core in an
            ASP.NET Core MVC web application.
        </p>
    </div>
    <div class="col-md-4">
        <h2>Build it from scratch</h2>
        <p>You can build the application by following the steps in a series of tutorials.</p>
        <p><a class="btn btn-default" href="https://docs.asp.net/en/latest/data/ef-mvc/intro.html">See the tutorial »</a></p>
    </div>
    <div class="col-md-4">
        <h2>Download it</h2>
        <p>You can download the completed project from GitHub.</p>
        <p><a class="btn btn-default" href="https://github.com/aspnet/Docs/tree/master/aspnetcore/data/ef-mvc/intro/samples/cu-final">See project source code »</a></p>
    </div>
</div>

按 CTRL+F5 运行品种或从菜单中选用 调试-> 初步执行(不调试),
您将在浏览器中观望本学科中落成的首页。

365bet体育投注 11

image.png

Entity Framework Core NuGet packages

翻译注: 此标题不翻译好过翻译
要在类型中添加 EF Core 帮衬,需求设置相应的数据库完结。本学科使用 SQL
Server 数据库,所须要的顺序包 Microsoft.EntityFrameworkCore.SqlServer
已经停放于 Microsoft.AspNetCore.All 包中,因而大家现在如何都无须做。

那么些程序包 (Microsoft.EntityFrameworkCore) 及其看重项
(Microsoft.EntityFrameworkCore.Relational) 提供了EF运行时辅助。在稍后的
”数据库迁移“教程中,你将会学习添加一个工具包。

至于可用于 Entity Framework Core 的别样数据库支持程序的信息,请参阅
Data
Providers

创设数据模型

接下去,您将为Contoso高校应用程序创设实体课程。 您将从以下七个实体先河。

365bet体育投注 12

class diagram

在 Student 与 Enrollement 实体间是一个一对多的关联, 在 Course 与
Enrollment 间也存在一些多关系。
换句话说,学生可以参预任意数量的学科,课程可以有自由数量的学员注册。

在以下部分中,您将为每个实体成立一个类。

Student 实体

在 Models 文件夹中,创造一个名为 Student.cs
的类公事,并应用以下代码替换模板代码。

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }
}

ID 属性将成为对应数据表的主键。默许意况下,Entity Framework 将名为 ID
或 {类名}ID 的特性解释为主键。
Enrollments
属性是导航属性。导航属性用于关联其余实体。对于一个学生实体(数据)来说,其中的
Enrollments 属性包括所有与该学生相关联的 Enrollment
实体(数据)。也就是说,如果数据库中的一个学生行数据涉嫌五个注册行数据(一对多,在
Enrollment 表中外键关联StudentID 值为该学员的主键值),则 Student
实体中的 Enrollments 导航属性将富含那五个 Enrollment 实体。

假若导航属性可以包容八个实体(在多对多或一对多涉及中),则其项目必须是足以增进,删除和换代条目的列表,例如ICollection
<T>。您可以指定ICollection <T>或项目,如List
<T>或HashSet <T>。假若指定ICollection
<T>,EF默许创立一个HashSet <T>集合。

Enrollment 实体

365bet体育投注 13

Enrollment

在 Models 文件夹中,创造一个名为 Student.cs
的类公事,并行使以下代码替换模板代码。

namespace ContosoUniversity.Models
{
    public enum Grade
    {
        A, B, C, D, F
    }

    public class Enrollment
    {
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }
        public Grade? Grade { get; set; }

        public Course Course { get; set; }
        public Student Student { get; set; }
    }
}

EnrollmentID 属性将改为主键。本实体使用 {类名}ID 形式代表在 Studnet
实体中运用的 ID 情势。 平日你会只选拔一种方式,并在方方面面数据模型中动用。
在此间,差别的格局是为了演示,表明你可以使用任一情势。
在前面的科目中,您将看到哪些利用没有类名的 ID
可以更便于地在数据模型中完成接二连三。

Grade (等级) 属性是一个枚举类型。 Grade 类型阐明后的 ? 表示
可为空类型。 一个空的阶段和一个值为0的等级是分化的 —
空表示等级未知或者尚未被赋值。

StudentID 属性是外键,相应的导航属性是 Student。 一个 Enrollment
实体与一个 Student 实体相关联,因而该属性只好拥有保留单个 Studnet
实体(与你往日看到的可以涵盖多个注册实体的 Student.Enrollments
导航属性分裂)。

CourseID 属性是外键, 对应的导航属性是 Course。 一个 Enrollment
实体与一个 Course 实体相关联。

当一个性质名称相符格局 <导航属性名><主键名> , EF
将质量解析为外键属性(例如,StudentID 对应 Student 导航属性,因为
Student 实体的主键是 ID)。 外键属性也得以简简单单地使用
<主键属性名称>(例如,CourseID,因为课程实体的主键是
CourseID)。

Course 实体

365bet体育投注 14

Course

在 Models 文件夹中,成立一个名为 Course.cs
的类公事,并接纳以下代码替换模板代码。

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Course
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }
}

Enrollments 属性是导航属性。一个 Course 实体可以提到到任意八个
Enrollment 实体。

俺们将在本种类的延续教程中详尽介绍 DatabaseGenerated 特性。
此特性允许你指定 Course 的主键名,而不是让数据库生成它。

创立数据库上下文 Database Context

将数据模型与 Entity Framework 功效协同工作的重大类是数据库上下文类。
通过从 Microsoft.EntityFrameworkCore.DbContext 类派生来创立此类。
在代码中,可以指定数据模型中包蕴怎样实体。 仍能自定义某些 Entity
Framework 行为。 在那一个种类中,该类被命名为 SchoolContext

在项目文件夹中,创制一个名为Data的文本夹。
在 Data 文件夹中成立一个名为 SchoolContext.cs
的新类,并用于下代码替换模板代码:

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
    public class SchoolContext : DbContext
    {
        public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
        {
        }

        public DbSet<Course> Courses { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Student> Students { get; set; }
    }
}

使用数据上下文 – 使用信赖注入

ASP.NET Core 默认使用信赖注入技术。
服务(如EF数据库上下文)在应用程序启动时期通过看重注入注册实例。
那多少个须要动用服务的机件通过构造函数参数得到劳动的实例。
稍后我们可以看到控制器构造函数获取上下文实例的代码。

要将 SchoolContext 注册为劳动,请打开 Startup.cs,并根据如下代码修改
ConfigureServices 方法。

//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<SchoolContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddMvc();
}

由此调用 DbContextOptionsBuilder
对象上的办法将连接字符串的称呼传递给上下文。 对于地点开发,ASP.NET Core
配置连串从 appsettings.json 文件读取连接字符串。

开辟appsettings.json文件并加上一个总是字符串,如下例所示。

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}
SQL Server Express LocalDB

连天字符串指定 SQL Server LocalDB 数据库。 LocalDB 是 SQL Server Express
数据库引擎的轻量级版本,目的在于用于应用程序开发,而不是生育用途。 LocalDB
按需启动并以用户方式运作,因而未曾复杂的陈设。 默许情形下,LocalDB在
C:/Users/<user> 目录中创设 .mdf 数据库文件。

累加代码,使用测试数据起头化数据库

EF 将为你成立一个空数据库。
在本节中,您将编制一个创办数据库后调用的主意,以便利用测试数据进行填空。

在这边,您将采纳 EnsureCreated 方法自动创制数据库。
在背后的科目中,您将见到哪些选取 Code First Migration (代码优先迁移)
来更改数据库架构而不是去除和重复创造数据库来拍卖架构更改。

Data 文件夹中,创造一个名为 DbInitializer.cs
的新类文件,并运用以下代码替换模板代码,这个代码将在必要时创制数据库,并将测试数据加载到新数据库中。

//DbInitializer.cs

using ContosoUniversity.Models;
using System;
using System.Linq;

namespace ContosoUniversity.Data
{
    public static class DbInitializer
    {
        public static void Initialize(SchoolContext context)
        {
            context.Database.EnsureCreated();

            // Look for any students.
            if (context.Students.Any())
            {
                return;   // DB has been seeded
            }

            var students = new Student[]
            {
            new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
            new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
            new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
            new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
            new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
            };
            foreach (Student s in students)
            {
                context.Students.Add(s);
            }
            context.SaveChanges();

            var courses = new Course[]
            {
            new Course{CourseID=1050,Title="Chemistry",Credits=3},
            new Course{CourseID=4022,Title="Microeconomics",Credits=3},
            new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
            new Course{CourseID=1045,Title="Calculus",Credits=4},
            new Course{CourseID=3141,Title="Trigonometry",Credits=4},
            new Course{CourseID=2021,Title="Composition",Credits=3},
            new Course{CourseID=2042,Title="Literature",Credits=4}
            };
            foreach (Course c in courses)
            {
                context.Courses.Add(c);
            }
            context.SaveChanges();

            var enrollments = new Enrollment[]
            {
            new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
            new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
            new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
            new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
            new Enrollment{StudentID=3,CourseID=1050},
            new Enrollment{StudentID=4,CourseID=1050},
            new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
            new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
            new Enrollment{StudentID=6,CourseID=1045},
            new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
            };
            foreach (Enrollment e in enrollments)
            {
                context.Enrollments.Add(e);
            }
            context.SaveChanges();
        }
    }
}

代码检查数据库中是否有学员,假设没有,则只要数据库是新的,并且须要采用测试数据进行种子。它将测试数据加载到数组而不是
List <T> 集合来优化品质。

在Program.cs中,修改Main方法在应用程序启动时执行以下操作:

  • 从看重注入容器获取数据库上下文实例。
  • 调用种子方法,传递给它的上下文。
  • 种子方法成功时销毁上下文。

public static void Main(string[] args)
{
    var host = BuildWebHost(args);

    using (var scope = host.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        try
        {
            var context = services.GetRequiredService<SchoolContext>();
            DbInitializer.Initialize(context);
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred while seeding the database.");
        }
    }

    host.Run();
}

在较旧的课程中,您或许会在Startup.cs中的Configure方法中看看类似的代码。
大家指出你仅使用Configure方法来设置请求管道。
应用程序启动代码属于Main方法。

首次运行应用程序时,将创建数据库并植入测试数据。
无论曾几何时转移数据模型,都能够去除数据库,更新种子方法,并以新的数据库重新开头重复启航。
在背后的教程中,您将见到在数据模型更改时怎样修改数据库,而不删除和重新创建它。

始建控制器和视图

接下去,您将利用 Visual Studio 脚手架拉长 MVC 控制器和视图,并行使 EF
来询问和保存数据。

电动创建CRUD操作方法和视图称为脚手架。
脚手架与代码生成器不一致之处在于,脚手架代码只是基础代码,您可以按照自己的内需展开修改,而普通情形下,您不会修改生成器生成的代码。
当您需求自定义生成器生成的代码,可以使用一些类,或者在情形时有暴发变更时时重新生成代码。

  • 右键单击解决方案资源管理器中的 Controllers 文件夹,然后采纳 添加
    -> 控制器。
  • 在“添加基架”对话框中,拔取“视图使用 Entity Framework 的 MVC
    控制器”,点击“添加”
  • 在“添加控制器”对话框中:
    • 模型类选拔 Student
    • 数码上下文类选拔 SchoolContext
    • 点击 “添加”。

365bet体育投注 15

new Controller

当你单击添加时,Visual Studio 脚手架引擎创造一个 StudentsController.cs
文件和一组与控制器一起行使的视图(.cshtml文件)。

(脚手架引擎还足以为您制造数据库上下文,要是你不像从前在本教程中那么手动创造它。
您可以经过单击数据上下文类右边的加号在“添加控制器”框中指定新的内外文类。
然后Visual Studio将成立您的DbContext类以及控制器和视图。)

你会小心到控制器将一个 SchoolContext 作为一个构造函数参数。

namespace ContosoUniversity.Controllers
{
    public class StudentsController : Controller
    {
        private readonly SchoolContext _context;

        public StudentsController(SchoolContext context)
        {
            _context = context;
        }

ASP.NET 依赖注入负责将 SchoolContext 的一个实例传递到控制器中。
前文中,已经
在 Startup.cs 文件中布局 SchoolContext 的依靠注入。

控制器包涵一个 Index 方法,用于浮现数据库中的所有学员。
该格局通过读取数据库上下文实例的 Students
属性获取学生实体集中的学童列表:

public async Task<IActionResult> Index()
{
    return View(await _context.Students.ToListAsync());
}

稍后将介绍此代码中的异步编程知识。

视图 Views/Students/Index.cshtml 使用 HTML 表格彰显学生列表。
(此处未对脚手架生成的代码举行其他改动,不再贴代码占用小说篇幅。 )

按 CTRL + F5 运行品种或从菜单中拔取 调试 -> 开始施行(不调试)。

单击 Student 链接,可以观望 DbInitializer.Initialize
方法中插入的测试数据。 根据浏览器窗口的狭小程度,您会看出页面顶部的
Student
链接,也有可能你必须单击右上角的导航图标才能观看隐藏菜单中的链接。

365bet体育投注 16

narrow Page

365bet体育投注 17

sdudent index

查看数据库

当您启动应用程序时,DbInitializer.Initialize 方法调用 EnsureCreated 。
EF 看到没有数据库,所以它创设了一个,然后 Initialize
方法代码的其他部分用数据填充数据库。 在 Visual Studio 中,您可以行使 SQL
Server 对象资源管理器(SSOX)查看数据库。

假诺 SSOX 窗口没有打开,在 Visual Studio 中,点击菜单 “视图” -> “SQL
Server 对象资源管理器”。
在 SSOX 中,单击(localdb)\ MSSQLLocalDB > 数据库,然后单击
ContosoUniversity1,也就是大家眼前在 appsettings.json
文件中装置的连年字符串中数据库名称。
开展“表”节点以查看数据库中的表。

365bet体育投注 18

ssox

右键单击 Student 表,然后单击 “查看数据”
以查看已开立的列和插入到表中的数据行。

365bet体育投注 19

student table

.mdf 和.ldf 数据库文件位于C:\Users<你的用户名> 文件夹中。
因为您在应用程序启动时运行的起初化程序方法中调用 EnsureCreated
,所以现在得以更改 Student
类,删除数据库,再一次运行应用程序,并活动重新成立数据库以出色您的变动。
例如,假若您将 EmailAddress 属性添加到 Student
类,则会在再度创制的表中看到一个新的EmailAddress 列。

约定

按照约定优于配备的规范,Entity Framework
构建一个数据库时,你所需书写的代码很少。

  • DbSet 属性的名称作为表名。
    对于未由DbSet属性引用的实业,实体类名用作表名。

  • 实业性质名称用于列名。

  • 名为 ID 或 classnameID 的实体性质被识别为主键属性。

  • 动用 导航属性名+实体主键名 命名的属性,会被自动识别为外键,例如:
    StudentID 由 Student (导航属性) + ID (Student实体主键名
    )组成。外键也得以省略只利用实体主键名,例如 EnrollmentID (外键) 与
    EnrollmentID (Enrollment 实体的主键)。

预订能够被遮住。例如,你可以显式指定表名,如本学科前面所观察的。
您能够设置列名称并将其余性质设置为主键或外键,那将在前面的教程中提及。

异步代码

ASP.NET Core和EF Core的默许使用异步编程。

Web
服务器的可用线程数量有限,在高负荷景况下,所有可用线程都可能都在使用。
当发生那种景况时,服务器不可以处理新的请求,直到线程被保释。
使用同步代码时,许多线程可能会被绑定,而实际上它们并没有做其余工作,因为它们正在等候
I/O 完成。 使用异步代码,当进度正在等候I/O
已毕时,其线程将被释放,供服务器用于拍卖任何请求。
由此,异步代码可以更实用地使用服务器资源,并且使服务器能够无延迟地拍卖更加多流量。

异步代码在运作时引入了少量的开发,但是对于低流量情况,质量下跌可以忽略不计,而对于高流量情状,潜在的习性提高是宏大的。
在偏下代码中,async 关键字, Task<T> 重回值,await 关键字和
ToListAsync 方法共同整合异步执行代码。

public async Task<IActionResult> Index()
{
    return View(await _context.Students.ToListAsync());
}
  • async 关键字告诉编译器为艺术体生成回调函数,并自行创制再次来到的
    Task <IActionResult> 对象。

  • 回来类型 Task<IActionResult> 表示正在拓展的做事,其结果类型为
    IActionResult365bet体育投注, 。

  • await 关键字告诉编译器将该措施分为两片段。
    第一片段以异步启动的操作截至。
    第二部分被放入回调方法,该操作在操作完结时被调用。

  • ToListAsyncToList 伸张方法的异步版本。

当你编写使用实体框架的异步代码时,要求专注的片段业务:

  • 唯有会引发查询或将指令发送到数据库的语句才要求异步执行。 那包蕴诸如
    ToListAsyncSingleOrDefaultAsyncSaveChangesAsync
    它不应有包罗,例如,只是改变IQueryable的讲话,类似
    var students = context.Students.Where(s => s.LastName == "Davolio")
    那样的语句。

  • EF上下文不是线程安全的:不要品味并行执行多个操作。 当您调用任何异步
    EF 方法时,请始终使用 await 关键字。

  • 借使你想利用异步代码的性质优势,请确保您正在利用的其他库包(例如用于分页)也利用异步,若是她们调用任何导致查询发送到数据库的办法。

有关.NET中异步编程的越来越多新闻,请参阅 Async
Overview

小结

您现在开立了一个简便的应用程序,使用 Entity Framework Core 和 SQL Server
Express LocalDB 存储和出示数据。 在底下的科目中,您将学习如何实施基本的
CRUD(创造,读取,更新和删除)操作。

相关文章

网站地图xml地图