澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

澳门新萄京官方网站:实体框架核心,全自动员

2019-06-08 作者:www.8455.com   |   浏览(189)

在开垦涉及到数据库的主次时,常会遇见壹开头布置的结构不可能满意须要要求再增添新字段或新表的情景,那时就须要张开数据库迁移。
得以实现数据库迁移有繁多种办法,从手动管理种种版本的ddl脚本,到落实协和的migrator,或是使用Entity Framework提供的Code First迁移功能。
Entity Framework提供的迁徙效率能够满意大多数人的供给,但仍会存在难以分项目管理迁移代码和易于出现"context has changed"错误的标题。

**译文,村办原创,转发请注明出处(C# 6 与 .NET Core 一.0 高档编程 - 38 章 实体框架核心(上)),不对的地方应接提出与沟通。** 

章节出自《Professional C# 陆 and .NET Core 一.0》。水平有限,各位阅读时精心鉴定区别,唯望莫误人子弟。

附英文版最初的作品:Professional C# 6 and .NET Core 1.0 - 38 Entity Framework Core

本章节译文分为上下篇,下篇见: C# 陆 与 .NET Core 一.0 高档编制程序 - 38 章 实体框架核心(下)


本章内容

  • Entity Framework Core 1.0简介
  • 选取注重注入实体框架
  • 创制关系模型
  • 使用.NET CLI工具和MSBuild进行搬迁
  • 指标追踪
  • 履新指标和目的树
  • 争辨管理与创新
  • 利用职业

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

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

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

**译文,私家原创,转发请表明出处(C# 6 与 .NET Core 1.0 高等编制程序 - 38 章 实体框架宗旨(上)),不对的地方迎接建议与调换。** 

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

附英文版原来的作品:Professional C# 6 and .NET Core 1.0 - 38 Entity Framework Core

本章节译文分为上下篇,下篇见: C# 六 与 .NET Core 一.0 高档编制程序 - 3捌 章 实体框架大旨(下)


本章内容

  • Entity Framework Core 1.0简介
  • 利用注重注入实体框架
  • 创办关系模型
  • 澳门新萄京官方网站,使用.NET CLI工具和MSBuild举办搬迁
  • 对象跟踪
  • 更新指标和对象树
  • 争持管理与更新
  • 行使职业

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

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

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

 【转载自

此地小编将介绍ZKWeb网页框架在Fluent NHibernate和Entity Framework Core上接纳的点子。
可以完结增加实体字段后,只需刷新网页就足以把更动应用到数据库。

实体框架的历史

实业框架是提供实体到关系的照射的框架。通过这种艺术,能够创设映射到数码库表的档案的次序,使用LINQ创立数据库查询,创制和换代目的,并将它们写入数据库。 

由此经过了很短的时间对Entity Framework的微量更换,最新的版本是三个完全的重写。一齐来看望Entity Framework的野史,以及重写的原因。

  • Entity Framework 1—Entity Framework的率先个本子未有备选好与.NET 3.伍相配,但它相当慢就足以与.NET 3.五 SP一包容。另多少个产品LINQ to SQL提供了一些近乎的成效,且已经可用于.NET 三.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 肆 在.NET 四中极其,并且获得了要害立异,在这之中诸多出自LINQ到SQL的主见。由于变化不小,版本二和三已被跳过。这几个版本里扩展了延期加载以获得访问属性的关系。在动用SQL数据定义语言(DDL)设计模型之后,能够创立数据库。今后选拔Entity Framework的四个模型是Database First或Model First。或许最要紧的风味是永葆轻易对象类(POCO),因而不再须要从基类EntityObject派生。

乘胜更新(举个例子Entity Framework 四.1,四.2),NuGet包增添了附加的功能,因此能更加快地加上效果。 Entity Framework 4.一提供了Code First模型,当中用于定义映射的EDMX文件不再行使。相反,全部的照耀都施用C#代码定义

  • 采用性质或Fluent API来定义的映射。

Entity Framework 四.二3日增了对搬迁的辅助。有了那一点,就足以行使C#代码定义数据库结构的转移。使用数据库从应用程序自动应用数据库更新。

  • Entity Framework 5—Entity Framework 伍的NuGet包扶助.NET 四.5和.NET 肆应用程序。不过,Entity Framework 5的重重功力都可用于.NET 四.伍。 Entity Framework仍旧基于.NET 四.5在系统上设置的品种。此版本的新扩张效益是性质立异以及帮衬新的SQL Server效率,比如空间数据类型。

  • Entity Framework 6—Entity Framework 6缓和了Entity Framework 5的一部分难点,个中有些是安装在系统上的框架的壹有的,壹部分因而NuGet扩大提供。近来Entity Framework的全数代码已移至NuGet包。为了不形成争持,使用了一个新的命名空间。将应用程序移植到新本寅时,必须改动命名空间。

本书琢磨Entity Framework的摩登版本,Entity Framework Core 一.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 壹.0不完全支持Entity Framework 陆提供的具备机能。随着时间的推迟,Entity Framework的新本子将提供更加的多效益,留意所选取的Entity Framework的本子。就算选取Entity Framework 6许多有力的理由,但在非Windows平台上选取ASP.NET Core 1.0、Entity Framework和通用Windows平台(UWP),以及非关周密据存款和储蓄,都亟需运用Entity Framework Core 一.0。 

本章介绍Entity Framework Core 一.0。从三个简单易行的模子读取和SQL Server中写入消息初叶,稍后会介绍增添关系,在写入数据库时将介绍更换追踪器和冲突管理。利用搬迁创立和修改数据库结构是本章的另二个最首要片段。 

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

实业框架的野史

实体框架是提供实体到事关的炫丽的框架。通过这种情势,能够创立映射到数量库表的花色,使用LINQ创设数据库查询,创设和更新指标,并将它们写入数据库。 

由此多年对Entity Framework的一些些修改,最新的本子是二个全然的重写。一同来探视Entity Framework的历史,以及重写的来由。

  • Entity Framework 1—Entity Framework的首先个版本未有计划好与.NET 3.五合作,但它高效就足以与.NET 3.5 SP一包容。另二个成品LINQ to SQL提供了部分近乎的效应,且早已可用于.NET 3.五。 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 肆 在.NET 肆中相称,并且获得了重在改正,在那之中十分的多来自LINQ到SQL的想法。由于变化相当大,版本2和三已被跳过。这几个本子里扩大了延期加载以获得访问属性的关系。在动用SQL数据定义语言(DDL)设计模型之后,可以创立数据库。现在选取Entity Framework的四个模型是Database First或Model First。只怕最要紧的特色是辅助简单对象类(POCO),因而不再需求从基类EntityObject派生。

乘胜更新(举个例子Entity Framework 四.一,4.2),NuGet包扩大了附加的功能,由此能更加快地加上效果。 Entity Framework 4.①提供了Code First模型,个中用于定义映射的EDMX文件不再采取。相反,全体的映射都利用C#代码定义

  • 使用性质或Fluent API来定义的照射。

Entity Framework 四.三充实了对搬迁的协助。有了那点,就足以行使C#代码定义数据库结构的转移。使用数据库从应用程序自动应用数据库更新。

  • Entity Framework 5—Entity Framework 五的NuGet包帮衬.NET 4.五和.NET 四应用程序。然则,Entity Framework 五的成都百货上千成效都可用于.NET 4.伍。 Entity Framework如故基于.NET 四.伍在系统上设置的门类。此版本的新扩大效益是性质立异以及协助新的SQL Server成效,比如空间数据类型。

  • Entity Framework 6—Entity Framework 陆化解了Entity Framework 5的一部分主题素材,个中有的是安装在系统上的框架的1局地,一部分由此NuGet扩张提供。如今Entity Framework的整个代码已移至NuGet包。为了不造成争辨,使用了多个新的命名空间。将应用程序移植到新本马时,必须改变命名空间。

本书探讨Entity Framework的摩登版本,Entity Framework Core 一.0。此版本是3个刨除旧的一坐一起周详重写,不再帮助CSDL,SSDL和MSL的XML文件映射,只帮忙Code First - 使用Entity Framework 四.一加上的模子。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 六提供的持有功用。随着时间的推迟,Entity Framework的新本子将提供越来越多效益,留意所使用的Entity Framework的版本。即便选取Entity Framework 六繁多有力的说辞,但在非Windows平台上行使ASP.NET Core 一.0、Entity Framework和通用Windows平台(UWP),以及非关周密据存款和储蓄,都急需接纳Entity Framework Core 一.0。 

本章介绍Entity Framework Core 1.0。从2个简约的模子读取和SQL Server中写入音讯开头,稍后会介绍增添关系,在写入数据库时将介绍改换追踪器和抵触管理。利用搬迁成立和修改数据库结构是本章的另八个重大片段。 

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

[C#/.NET]Entity Framework(EF) Code First 多对多涉及的实体增,删,改,查操作全程详细示例

正文大家来读书一下在Entity Framework中利用Context删除多对多涉及的实业是如何来促成的。我们将以多少个有血有肉的调节台小实例来打听和读书整个完结Entity Framework 多对多关系的实业删除的操作进度。

完结机关迁移的思路

数据库迁移要求钦定改造的片段,举例增添表和增进字段。
而落到实处全自动员搬迁移须求自动生成那么些退换的部分,具体来讲供给

  • 获得数据库现成的协会
  • 获得代码中幸存的结构
  • 相对来说结构之间的出入并生成迁移

那正是Entity Framework的Add-Migration(或dotnet ef migrations add)命令所做的工作,
接下去大家将看怎样不使用那类的授命,在NHibernate, Entity Framework和Entity Framework Core中贯彻全自动的管理。

实业框架简要介绍

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

在首先个示范中,首先创制数据库。能够选取Visual Studio 二零一五中的SQL Server对象资源管理器推行此操作。选用数据库实例(与Visual Studio一同安装的(localdb) 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
)

实业框架简单介绍

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

在首先个示范中,首先成立数据库。能够应用Visual Studio 二〇一五中的SQL Server对象财富管理器试行此操作。接纳数据库实例(与Visual Studio一同安装的(localdb) MSSQLLocalDB),单击树视图中的数据库节点,然后选拔“增添新数据库”。示例数据库唯有3个名称为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
)

你将学习到

  • 哪些创制四个引用Entity Framework的品类;

  • 怎么配置Entity Framework的数据库连接;

  • 什么去掉Entity Framework Code First 生成的表名的复数;

  • 哪些通过EntityTypeConfiguartion<T>配置实体的Fluent API ;

  • 怎么配置Entity Framework的实业多对多的关联映射;

  • Entity Framework数据早先化;

  • 何以使用包管理工科具调控台来变化和立异数据库;

  • 怎么删除Entity Framework中的多对多关系的数额。

Fluent NHibernate的机关迁移

ZKWeb框架使用的完全代码能够翻看这里

首先Fluent NHibernate要求增加全数实体的映射类型,以下是生成配置和增加实业映射类型的例子。
配置类的组织能够翻看这里

var db = MsSqlConfiguration.MsSql2008.ConnectionString("连接字符串");
var configuration = Fluently.Configure();
configuration.Database(db);
configuration.Mappings(m => {
    m.FluentMappings.Add(typeof(FooEntityMap));
    m.FluentMappings.Add(typeof(BarEntityMap));
    ...
});

接下去是把装有实体的组织丰硕或更新到数据库。
NHibernate提供了SchemaUpdate,那一个类能够自动物检疫验数据库中是否业已有表或字段,未有的时候自动抬高。
应用格局特别简单,以下是采纳的例证

configuration.ExposeConfiguration(c => {
    // 第一个参数 false: 不把语句输出到控制台
    // 第二个参数 true: 实际在数据库中执行语句
    new SchemaUpdate(c).Execute(false, true);
});

到这一步就早已落到实处了机关迁移,但大家还应该有创新的余地。
因为SchemaUpdate不保留境况,每回都要检查评定数据库中的整个结构,所以进行起来EF的搬迁要缓慢诸多,
ZKWeb框架为了减弱每一遍运营网址的光阴,在实行更新在此以前还大概会检查测试是还是不是须要更新。

var scriptBuilder = new StringBuilder();
scriptBuilder.AppendLine("/* this file is for database migration checking, don't execute it */");
new SchemaExport(c).Create(s => scriptBuilder.AppendLine(s), false);
var script = scriptBuilder.ToString();
if (!File.Exists(ddlPath) || script != File.ReadAllText(ddlPath)) {
    new SchemaUpdate(c).Execute(false, true);
    onBuildFactorySuccess = () => File.WriteAllText(ddlPath, script);
}

这段代码应用了SchemaExport来扭转全部表的DDL脚本,生成后和上次的变型结果相比,不平等时才调用SchemaUpdate更新。

NHibernate提供的机动员搬迁移有以下的特色,使用时应该小心

  • 字段只会助长,不会删除,假设你重命名了字段原来的字段也会保留在数据库中
  • 字段类型倘若更改,数据库不会随之变动
  • 涉嫌的外键就算改动,迁移时有希望会出错

总括NHibernate的自动员搬迁移只会增加表和字段,基本不会修改原有的构造,有早晚的界定只是比较安全。

创造模型 

用于访问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

 澳门新萄京官方网站 1

图 38.1  

Book类是1个简练的实体类型,它定义了多个属性。 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; }
}

创办模型 

用以访问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

 澳门新萄京官方网站 2

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

本示例开荒条件

  • 操作系统:Windows 十

  • 开采工具及版本:Visual Studio 20一5 Update 1

  • .NET Framework版本:.NET Framework 4.6

  • 次第输出格局:调控台应用程序

Entity Framework的自行迁移

ZKWeb框架未有辅助Entity Framework 陆,但落到实处比较轻便小编就直接上代码了。
例子

// 调用静态函数,放到程序启动时即可
// Database是System.Data.Entity.Database
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, MyConfiguration>());

public class MyConfiguration : DbMigrationsConfiguration<MyContext> {
    public MyConfiguration() {
        AutomaticMigrationsEnabled = true; // 启用自动迁移功能
        AutomaticMigrationDataLossAllowed = true; // 允许自动删字段,危险但是不加这个不能重命名字段
    }
}

Entity Framework提供的活动员搬迁移有以下的性状,使用时应当小心

  • 假使字段重命名,旧的字段会被删除掉,推荐做好数据的备份和尽量幸免重命名字段
  • 外键关联和字段类型都会自行生成,变化时有相当的大概率会招致原有的数目丢失
  • 自动员搬迁移的记录和应用工具迁移同样,都会保存在__MigrationHistory表中,切勿混用不然代码将不能够用到新的数据库中

小结Entity Framework的迁移能够保险实体和数据库之间很强的1致性,不过使用不当会招致原有数据的不见,请务必做好数据库的定时备份。

创办上下文 

创设的BooksContext类实现Book表与数据库的关系。那个类派生自基类DbContext,BooksContext类定义Books属性类型为DbSet <Book>。此类型允许创立查询并加多Book实例以将其积存在数据库中。要定义连接字符串,能够重写DbContext的OnConfiguring方法。UseSqlServer增加方法将左右文映射到SQL Server数据库(代码文件Books萨姆ple / 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);
  }
}

概念连接字符串的另叁个抉择是接纳注重注入,就要本章后边介绍。 

始建上下文 

创办的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);
  }
}

概念连接字符串的另三个摘取是采用正视注入,将要本章后边介绍。 

先是步、成立项目并引述程序包

Entity Framework Core的机动员搬迁移

Entity Framework Core去掉了SetInitializer分选,代替他的是DatabaseFacade.MigrateDatabaseFacade.EnsureCreated
DatabaseFacade.Migrate能够行使使用ef命令生成的搬迁代码,防止在生产条件中实施ef命令。
DatabaseFacade.EnsureCreated则开端成立全体数据表和字段,但不得不创立不能够立异,不会加多纪录到__MigrationHistory
那七个函数都不能够促成全自动员搬迁移,ZKWeb框架使用了EF内部提供的函数,完整代码能够翻开这里

Entity Framework Core的活动员搬迁移实现比较复杂,咱们需求分两步走。

  • 先是步 创设迁移记录__ZKWeb_MigrationHistory表,那几个表和EF自带的协会同样,但以此表是给本身用的不是给ef命令用的
  • 其次部 查找最终一条迁移记录,和最近的结构实行自己检查自纠,寻觅异样并立异数据库

先是步的代码应用了EnsureCreated创设数据库和迁移记录表,个中EFCoreDatabaseContextBase只有迁移记录一个表。
创设完未来还要把带迁移记录的组织保留下来,用作前边的对照,借使这里不保留会导致迁移记录的双重创造错误。

using (var context = new EFCoreDatabaseContextBase(Database, ConnectionString)) {
    // We may need create a new database and migration history table
    // It's done here
    context.Database.EnsureCreated();
    initialModel = context.Model;
}

在实行第1步事先,还要求先决断连接的数据库是或不是关周详据库,
因为Entity Framework Core现在还大概会支持redis mongodb等非关系型数据库,自动员搬迁移只应该用在关周详据库中。

using (var context = new EFCoreDatabaseContext(Database, ConnectionString)) {
    var serviceProvider = ((IInfrastructure<IServiceProvider>)context).Instance;
    var databaseCreator = serviceProvider.GetService<IDatabaseCreator>();
    if (databaseCreator is IRelationalDatabaseCreator) {
        // It's a relational database, create and apply the migration
        MigrateRelationalDatabase(context, initialModel);
    } else {
        // It maybe an in-memory database or no-sql database, do nothing
    }
}

第叁步需求寻觅最终一条迁移记录,和眼下的构造进行对照,找寻差别并更新数据库。

先看迁移记录表的剧情,迁移记录表中有四个字段

  • Revision 每一次迁移都会 一
  • Model 当前的协会,格式是c#代码
  • ProductVersion 迁移时Entity Framework Core的版本号

Model存放的代码例子如下,这段代码记录了全体表的全数字段的定义,是自动生成的。
背后小编将会讲课怎样生成这段代码。

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using ZKWeb.ORM.EFCore;

namespace ZKWeb.ORM.EFCore.Migrations
{
    [DbContext(typeof(EFCoreDatabaseContext))]
    partial class Migration_636089159513819123 : ModelSnapshot
    {
        protected override void BuildModel(ModelBuilder modelBuilder)
        {
            modelBuilder
                .HasAnnotation("ProductVersion", "1.0.0-rtm-21431")
                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

            modelBuilder.Entity("Example.Entities.Foo", b =>
                {
                    b.Property<Guid>("Id")
                        .ValueGeneratedOnAdd();

                    b.Property<string>("Name")
                        .IsRequired();
                });
            }
        }
    }
}

接下去查找最终一条迁移记录:

var lastModel = initialModel;
var histories = context.Set<EFCoreMigrationHistory>();
var lastMigration = histories.OrderByDescending(h => h.Revision).FirstOrDefault();

留存时,编写翻译Model中的代码并且赢得ModelSnapshot.Model的值,那么些值便是上一遍迁移时的欧洲经济共同体结构。
不设一时,将应用initialModel的结构。
编写翻译使用的是其它三个零部件,你也足以用Roslyn CSharpScripting包提供的接口编写翻译。

if (lastMigration != null) {
    // Remove old snapshot code and assembly
    var tempPath = Path.GetTempPath();
    foreach (var file in Directory.EnumerateFiles(
        tempPath, ModelSnapshotFilePrefix   "*").ToList()) {
        try { File.Delete(file); } catch { }
    }
    // Write snapshot code to temp directory and compile it to assembly
    var assemblyName = ModelSnapshotFilePrefix   DateTime.UtcNow.Ticks;
    var codePath = Path.Combine(tempPath, assemblyName   ".cs");
    var assemblyPath = Path.Combine(tempPath, assemblyName   ".dll");
    var compileService = Application.Ioc.Resolve<ICompilerService>();
    var assemblyLoader = Application.Ioc.Resolve<IAssemblyLoader>();
    File.WriteAllText(codePath, lastMigration.Model);
    compileService.Compile(new[] { codePath }, assemblyName, assemblyPath);
    // Load assembly and create the snapshot instance
    var assembly = assemblyLoader.LoadFile(assemblyPath);
    var snapshot = (ModelSnapshot)Activator.CreateInstance(
        assembly.GetTypes().First(t =>
        typeof(ModelSnapshot).GetTypeInfo().IsAssignableFrom(t)));
    lastModel = snapshot.Model;
}

和脚下的布局实行自己检查自纠:

// Compare with the newest model
var modelDiffer = serviceProvider.GetService<IMigrationsModelDiffer>();
var sqlGenerator = serviceProvider.GetService<IMigrationsSqlGenerator>();
var commandExecutor = serviceProvider.GetService<IMigrationCommandExecutor>();
var operations = modelDiffer.GetDifferences(lastModel, context.Model);
if (operations.Count <= 0) {
    // There no difference
    return;
}

假定有异样,生成迁移命令(commands)和当下总体结构的快照(modelSnapshot)。
地点Model中的代码由这里的CSharpMigrationsGenerator生成,modelSnapshot的品类是string

// There some difference, we need perform the migration
var commands = sqlGenerator.Generate(operations, context.Model);
var connection = serviceProvider.GetService<IRelationalConnection>();
// Take a snapshot to the newest model
var codeHelper = new CSharpHelper();
var generator = new CSharpMigrationsGenerator(
    codeHelper,
    new CSharpMigrationOperationGenerator(codeHelper),
    new CSharpSnapshotGenerator(codeHelper));
var modelSnapshot = generator.GenerateSnapshot(
    ModelSnapshotNamespace, context.GetType(),
    ModelSnapshotClassPrefix   DateTime.UtcNow.Ticks, context.Model);

安排迁移记录并实行迁移命令:

// Insert the history first, if migration failed, delete it
var history = new EFCoreMigrationHistory(modelSnapshot);
histories.Add(history);
context.SaveChanges();
try {
    // Execute migration commands
    commandExecutor.ExecuteNonQuery(commands, connection);
} catch {
    histories.Remove(history);
    context.SaveChanges();
    throw;
}

到那边就到位了Entity Framework Core的自行迁移,现在每一趟有更新都会比较最终一回迁移时的布局并实施更新。
Entity Framework Core的动员搬迁特点和Entity Framework同样,能够确认保证很强的一致性但须求注意幸免数据的遗失。

写入数据库

于今已开立了有Books表的数据库,也定义了模型和内外文类,然后能够用数据填充表。创造AddBookAsync方法将Book对象增多到数据库。首先,BooksContext对象被实例化,这里运用using语句确认保证数据库连接关闭。使用Add方法将对象加多到上下文之后,实体被写入调用SaveChangesAsync的数据库(代码文件Books萨姆ple / 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方法(代码文件BooksSample / 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对象财富管理器查看写入到数据库的数码。

写入数据库

今昔已创立了有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方法(代码文件BooksSample / 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对象能源管理器查看写入到数据库的数额。

一.一 创设项目

率先,我们创立3个调节台应用程序,取名叫:EFRemoveManyToMany德姆o,如下图:

澳门新萄京官方网站 3

 

澳门新萄京官方网站 4

写在结尾

机关迁移数据库要是没有错使用,能够抓实项目中相继模块的独立性,收缩支出和安顿的专门的学问量。
可是因为不能够手动控制搬迁内容,有自然的受制和险恶,需求精通好应用的O昂CoraM迁移的特征。

从数据库读取

从C#代码读取数据只要求调用BooksContext并访问Books属性。访问此属性会创制三个SQL语句从数据库中搜索全体书籍(代码文件BooksSample / Program.cs):

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

在调整时期打开速龙liTrace 伊夫nts窗口,能够看来发送到数据库的SQL语句(供给Visual Studio 公司版):

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

Framework提供了1个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'

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

从数据库读取

从C#代码读取数据只须求调用BooksContext并访问Books属性。访问此属性会创制1个SQL语句从数据库中追寻全数书籍(代码文件BooksSample / Program.cs):

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提供了1个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'

*注意 在第三叁章“语言集成查询”中详尽商讨了LINQ。
*

一.2 引用程序包

随之张开程序包管理工具,安装必须的EntityFramework引用包,如下:

澳门新萄京官方网站 5

 

澳门新萄京官方网站 6

写在终极的广告

ZKWeb网页框架曾经在实质上项目中选拔了那项本事,近日来看迁移部分依然相比较稳固的。
那项本领最初是为着插件市廛而支付的,在下载安装插件未来无需再度编写翻译主程序,无需施行其余迁移命令就能够应用。
此时此刻虽说尚未落到实处插件商号,也回落了累累清淡无奇开支的办事。

1旦您有意思味,欢迎参与ZKWeb交换群5220838八陆共同查究。

更新记录

只需改换已加载上下文的对象并调用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();
}

更新记录

只需更动已加载上下文的对象并调用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();
}

第3步、创立实体类并布置数据库连接

剔除记录

终极,让大家清理数据库并剔除全部记录。能够透过搜寻全数记录并调用Remove或RemoveRange方法来设置上下文中要删减的靶子的景况。然后调用SaveChangesAsync方法就能够从数据库中删去记录,DbContext会为种种要刨除的指标调用SQL Delete语句(代码文件BooksSample / 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)在毫不在全体方案中都可用。使用示例代码不能够有效地删除全部目的。您能够动用三个SQL语句删除全体而不是逐条删除记录。在第壹柒章“ADO.NET”中解释了怎么着达成这或多或少。*

问询了哪些增加、查询、更新和删除记录,本章将介绍幕后的效果,并应用Entity Framework进入高级场景。

剔除记录

末段,让大家清理数据库并删除全数记录。可以经过搜索全部记录并调用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)在毫不在具有方案中都可用。使用示例代码不能够有效地删除全部目的。您能够行使多个SQL语句删除全部而不是逐条删除记录。在第三7章“ADO.NET”中表明了什么做到那或多或少。*

明白了怎么加多、查询、更新和删除记录,本章将介绍幕后的功力,并使用Entity Framework进入高等场景。

2.1 创造实体类

设置好Entity Framework包之后 ,大家先创设本示例供给的几个实体对应的类:User和Role(都投身Model的公文夹下),如下:

User.cs

 1 using System;
 2 using System.Collections.Generic;
 3 
 4 namespace EFRemoveManyToManyDemo.Model
 5 {
 6     public class User
 7     {
 8         public User()
 9         {
10             Roles = new HashSet<Role>();
11         }
12         public int Id { get; set; }
13         public string FirstName { get; set; }
14         public string LastName { get; set; }
15         public DateTime? CreatedOn { get; set; }
16         public virtual ICollection<Role> Roles { get; set; }//多对多关系中两边都要写上ICollection
17     }
18 }

 

Role.cs

 1 using System.Collections.Generic;
 2 
 3 namespace EFRemoveManyToManyDemo.Model
 4 {
 5     public class Role
 6     {
 7         public Role()
 8         {
 9             this.Users = new HashSet<User>();!!依赖注入中的构造器注入
10         }
11         public int Id { get; set; }
12         public string Name { get; set; }
13 
14         public virtual ICollection<User> Users { get; set; }
15         //多对多关系中两边都要写上ICollection
16     }
17 }

 

应用信赖注入  

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与上四个演示中的这几个点子13分相似,但他俩选取BooksService类的上下文成员,而不是创造2个新的(代码文件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();
}

运营应用程序能够看到记录已增加到图书数据库中然后从中读取记录。

*注意 在第③一章“XAML应用程序的方式”中阅读有关注重注入和Microsoft.Framework.DependencyInjection包的越来越多消息,还足以参见第伍0章“ASP.NET Core”和第四一章“ ASP.NET MVC“。*

应用重视注入  

Entity Framework Core 一.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属性(代码文件Books萨姆pleWithDI / BooksContext.cs):

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

BooksService是使用BooksContext的新类。BooksContext通过注入构造函数注入。方法AddBooksAsync和ReadBooks与上3个演示中的这几个点子丰硕相像,但他俩运用BooksService类的上下文成员,而不是创办贰个新的(代码文件BooksSampleWithDI / 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方法要求3个Action委托作为参数,个中接收到2个DbContextOptionsBuilder参数。有了该选项参数,能够应用UseSqlServer扩张方法配置上下文。这里用Entity Framework注册SQL Server与上多个示范是看似的效应(代码文件Books萨姆pleWithDI / 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();
}

运行应用程序能够看到记录已增加到图书数据库中然后从中读取记录。

*注意 在第1一章“XAML应用程序的形式”中读书有关依赖注入和Microsoft.Framework.DependencyInjection包的更加多新闻,还足以参见第四0章“ASP.NET Core”和第肆一章“ ASP.NET MVC“。*

2.2 配置Fluent API

为了布署Fluent API,新建一个Mapping文件夹,再分别创设User的布局文件UserConfigurationMapping和Role的布局文件RoleConfigurationMapping,如下:

UserConfiguration.cs

using EFRemoveManyToManyDemo.Model;
using System.Data.Entity.ModelConfiguration;

namespace EFRemoveManyToManyDemo.Mapping
{
    public class UserConfigurationMapping : EntityTypeConfiguration<User>
    {
        public UserConfigurationMapping()
        {
            Property(x => x.FirstName).HasMaxLength(50).IsRequired();
            Property(x => x.LastName).HasMaxLength(50).IsRequired();
        }
    }
}

 

RoleConfigurationMapping.cs

 1 using EFRemoveManyToManyDemo.Model;
 2 using System.Data.Entity.ModelConfiguration;
 3 
 4 namespace EFRemoveManyToManyDemo.Mapping
 5 {
 6     public class RoleConfigurationMapping : EntityTypeConfiguration<Role>
 7     {
 8         public RoleConfigurationMapping()
 9         {
10             HasKey(x => x.Id);
11             Property(x => x.Name).HasMaxLength(50).IsRequired();
12             HasMany(x => x.Users)
13                 .WithMany(x => x.Roles)
14                 .Map(m =>
15                 {
16                     m.MapLeftKey("RoleId");
17                     m.MapRightKey("UserId");
18                     m.ToTable("LNK_User_Role");
19                 });
20         }
21     }
22 }

 

创设模型  

本章的率先个示例映射单个表。第四个例子展现了创设表之间的涉嫌。在本节中选取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

创建立模型型  

本章的第多个示例映射单个表。第三个例证展现了成立表之间的涉嫌。在本节中使用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

2.3 创建Context类

接下去,我们再成立八个名字为:ManyToManyRemoveContext的类,该类承继至DbContext类,用于管理数据库的总是上下文和数据库早先化等的片段配备和操作,如下:

using EFRemoveManyToManyDemo.Mapping;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace EFRemoveManyToManyDemo
{
    public class ManyToManyRemoveContext : DbContext
    {
        public ManyToManyRemoveContext() : base("ManyToManyRemoveContext")
        {

        }
    }
}

 

创办关系

让大家初始创办多个模子。示例项目选用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):

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

创制关系

让咱们发轫创办二个模型。示例项目选取MenuCard和Menu类型定义一对多关系。MenuCard包罗Menu对象的列表。这种涉及由List <Menu>类型的Menu属性轻易定义(代码文件MenusSample / Menu卡德.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 属性去定义外键关系(代码文件Menus萨姆ple / Menu.cs):

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(代码文件MenusSamples / 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);
  }
}

二.四 配置连接字符串

再在App.config配置文件中加多本地的数据库连接字符串,大约如下(具体的请依据你的莫过于数据连接参数来):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
  </startup>
  <connectionStrings>
    <add name="ManyToManyRemoveContext" connectionString="server=你的数据库服务器地址;database=ManyToManyRemoveDemo;uid=你的数据库登录名;pwd=密码" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="mssqllocaldb" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

 

使用.NET CLI进行搬迁

要使用C#代码自动创立数据库,能够选用enet工具使用package dotnet-ef扩张.NET CLI工具。此软件手袋含用于为搬迁创造C#代码的指令。通过设置dotnet-ef NuGet包能够职责令可用。您可以透过从项目配置文件(代码文件MenusSample / project.json)中的工具部分引用此软件包来安装它:

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

ef命令提供以下命令:数据库、dbcontext和迁移。数据库命令用于将数据库晋级到特定的迁徙景况。 dbcontext命令列出项目中的全部DbContext派生类型(dbcontext list),并从数据库(dbcontext scaffold)创建上下文和实业。 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");
  }
}

注意 正在实行的每一种改动都得以创立另1个搬迁。新搬迁仅定义从原先版本到新本子所需的更动。如若客户的数据库需求从随机早期的本子更新,迁移数据库时调用需求的搬迁。 

在支付进程中,也行无需全数的动员搬迁,恐怕需求从品类中开创,因为恐怕没有该类不常气象的数据仓库储存在。在这种情形下能够去除迁移并创办三个相当的大的新搬迁。

使用.NET CLI进行搬迁

要使用C#代码自动创造数据库,能够采取enet工具使用package dotnet-ef扩充.NET CLI工具。此软件公文包含用于为搬迁创设C#代码的通令。通过设置dotnet-ef NuGet包能够职务令可用。您能够透过从类别配置文件(代码文件MenusSample / project.json)中的工具部分引用此软件包来设置它:

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

ef命令提供以下命令:数据库、dbcontext和迁移。数据库命令用于将数据库晋级到特定的迁移景况。 dbcontext命令列出项目中的全部DbContext派生类型(dbcontext list),并从数据库(dbcontext scaffold)成立上下文和实体。 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");
  }
}

注意 正在进展的各样改换都足以创设另2个搬迁。新搬迁仅定义从在此以前版本到新本子所需的改观。假若客户的数据库须求从随机早期的本子更新,迁移数据库时调用须要的迁移。 

在付出进度中,也行无需有所的迁徙,只怕必要从品类中开创,因为或许未有该类不经常气象的数据仓库储存在。在这种景况下能够去除迁移并创立三个很大的新搬迁。

2.5 重写Context

为了将大家刚刚写的Fluent API应用到相应的实体上,所以我们供给重写(override)DbContext的OnModelCreating方法,如下:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            modelBuilder.Configurations.Add(new UserConfigurationMapping());
            modelBuilder.Configurations.Add(new RoleConfigurationMapping());
        }

 

其中

modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

  是将Entity Framework Code First在实业类生成对应表时去掉表名的复数用的。简单地说就是,私下认可情状下,Entity Framework Code First在由实体类生成对应表时的表名是复数形式的,举个例子本例的User和Role类,假如未有那句配置,在转换表名的时候将会是Users和Roles那三个表名,反之,则是User和Role那八个表名。

好了,下边贴出完整的ManyToManyRemoveContext.cs文件的代码:

 1 using EFRemoveManyToManyDemo.Mapping;
 2 using EFRemoveManyToManyDemo.Model;
 3 using System.Data.Entity;
 4 using System.Data.Entity.ModelConfiguration.Conventions;
 5 
 6 namespace EFRemoveManyToManyDemo
 7 {
 8     public class ManyToManyRemoveContext : DbContext
 9     {
10         public ManyToManyRemoveContext() : base("ManyToManyRemoveContext")
11         {
12 
13         }
14 
15         protected override void OnModelCreating(DbModelBuilder modelBuilder)
16         {
17             base.OnModelCreating(modelBuilder);
18             modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
19 
20             modelBuilder.Configurations.Add(new UserConfigurationMapping());
21             modelBuilder.Configurations.Add(new RoleConfigurationMapping());
22         }
23 
24         public DbSet<User> Users { get; set; }
25         public DbSet<Role> Roles { get; set; }
26     }
27 }

 

正文写到这里,关于Entity Framework的引用,实体类的宣示和Fluent API配置以及与数据库连接等操作都已成功了。接下来我们要做的是应用Entity Framework所实体生成到安插好的数据库中。

应用MSBuild实行搬迁  

假如您正在利用基于MSBuild的项目Entity Framework迁移而不是DNX,迁移命令是例外的。使用完全框架调整台应用程序、WPF应用程序或ASP.NET 四.陆种类连串,要求在NuGet包管理器调控台北内定迁移命令,而不是开荒人士命令提醒符。从Visual Studio通过 工具➪库管理器调节台➪包管理器调控台 运转包管理器调节台。

在包管理器调控台能够选取PowerShell脚本加多和删除迁移。命令如下

> Add-Migration InitMenuCards

开创贰个Migrations文件夹,在那之中涵盖如前所示的迁移类。

创制数据库 

趁着迁移类型变成,能够成立数据库。 DbContext派生类MenusContext包蕴3个回去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。基于私下认可约定,表与实体类型是同一的称号。另3个约定用于创制主键:Menu卡德Id列会被定义为主键,因为属性名以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表定义了Menu卡德Id,它是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 列的高低能够从NVA大切诺基CHA中华V(MAX)减小,SQL Server定义了可用以Price列的Money类型,并且组织名称能够从dbo改动。 Entity Framework提供了多个挑选从代码中施行那么些退换:数据批注和Fluent API,下边将切磋。

数据批注

潜移默化生成的数据库的1种情势是向实体类型丰硕数据注释。能够使用Table属性改变表的称谓。要改成结构名称,Table属性定义Schema属性。借使要为字符串类型钦命差别的长度,可以选用马克斯Length属性(代码文件MenusWithDataAnnotations / MenuCard.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
);

接纳MSBuild实行搬迁  

如果你正在利用基于MSBuild的项目Entity Framework迁移而不是DNX,迁移命令是例外的。使用完整框架调控台应用程序、WPF应用程序或ASP.NET 四.6档案的次序项目,须求在NuGet包管理器调控新竹钦定迁移命令,而不是开辟职员命令提示符。从Visual Studio通过 工具➪库处理器调整台➪包管理器调整台 运维包管理器调整台。

在包管理器调整台能够动用PowerShell脚本增添和删除迁移。命令如下

> Add-Migration InitMenuCards

创建1个Migrations文件夹,其中包蕴如前所示的迁移类。

成立数据库 

乘胜迁移类型产生,能够创建数据库。 DbContext派生类MenusContext包涵贰个回到DatabaseFacade对象的Database属性。使用DatabaseFacade能够创设和删除数据库。如若数据库不设有,EnsureCreated方法会创立数据库;假如数据库已存在,则不进行此外操作。方法EnsureDeletedAsync删除数据库。以下代码片段创制数据库(就算它不存在)(代码文件MenusSample / 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 列的轻重能够从NVA翼虎CHA安德拉(MAX)减小,SQL Server定义了可用以Price列的Money类型,并且协会名称可以从dbo改换。 Entity Framework提供了两个挑选从代码中实行这个更换:数据讲授和Fluent API,上面将研讨。

多少讲明

影响生成的数据库的壹种艺术是向实体类型丰硕数据注释。能够选拔Table属性改换表的名号。要改成结构名称,Table属性定义Schema属性。要是要为字符串类型内定不一样的长度,能够利用马克斯Length属性(代码文件MenusWithDataAnnotations / MenuCard.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
);

其三步、应用Migration生成数据库

在接下去的历程中,大家会用到包管控台(Package Manager Console)和八个指令:

Fluent API  

潜移默化创制的表的另1种方法是选用Fluent API中DbContext派生类的OnModelCreating方法。它的优点是足以保持实体类型大概,而不增多其他性质,Fluent API还提供了比选择品质越来越多的选项。 

以下代码片段展现了BooksContext类重写OnModelCreating方法。作为参数接收的ModelBuilder类提供了部分办法,并定义了三种扩张方法。 HasDefaultSchema是当中1个扩展方法,它将私下认可结构接纳于当下有着项目标模型。 Entity方法重回二个EntityTypeBuilder,使您能够自定义实体,比方将其映射到特定的表名和定义键和目录(代码文件MenusSample / MenusContext.cs):

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类型的属性,并钦点是或不是应自动生成值(比方标记列):

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定义映射方法去定义1对多映射。HasMany 结合 WithOne 方法定义了多Menus 和三个Menu Card 的映照。 HasMany需求与WithOne链接,即HasOne方法供给1个带WithMany或WithOne的链。链接 HasOne 和 WithMany定义了1对多关系,链接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方法中开创映射之后方可创设如前所示的动员搬迁。

Fluent API  

潜移默化创造的表的另壹种方法是应用Fluent API中DbContext派生类的OnModelCreating方法。它的帮助和益处是足以保证实体类型差不离,而不加多其余性质,Fluent API还提供了比使用品质更加多的选项。 

以下代码片段突显了BooksContext类重写OnModelCreating方法。作为参数接收的ModelBuilder类提供了一部分措施,并定义了二种扩展方法。 HasDefaultSchema是个中一个扩展方法,它将暗中认可结构采纳于当下有所品类的模子。 Entity方法重回1个EntityTypeBuilder,令你能够自定义实体,譬喻将其映射到一定的表名和定义键和目录(代码文件MenusSample / MenusContext.cs):

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定义了3个Property方法来配置属性。 Property方法再次回到PropertyBuilder,能够依次配置具备最大尺寸值,须求的装置和SQL类型的天性,并点名是或不是应自动生成值(比如标志列):

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方法需求1个带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方法中开创映射之后能够创制如前所示的动员搬迁。

3.1 Enable-Migrations

命令使用方法如下图:

澳门新萄京官方网站 7

 

澳门新萄京官方网站 8

运行以上命令后,Entity Framework会自动在我们的花色中开创三个名称为Migrations的文本夹,同时生成一个Configuartion.cs的配置文件。那时的种类组织概略上是那样的:

澳门新萄京官方网站 9

 

澳门新萄京官方网站 10

转移好Configuration.cs的公文大家再作多少的起始化,如下:

namespace EFRemoveManyToManyDemo.Migrations
{
    using Model;
    using System;
    using System.Collections.Generic;
    using System.Data.Entity.Migrations;
    using System.Linq;
    internal sealed class Configuration : DbMigrationsConfiguration<ManyToManyRemoveContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }

        protected override void Seed(ManyToManyRemoveContext context)
        {
            var roles = new List<Role> {
                new Role{ Id=1,Name="超级管理员" },
                new Role{ Id=2,Name="管理员" },
                new Role{ Id=3,Name="一般用户" }
            };

            var users = new List<User> {
                new User {Id=1,FirstName="Kobe",LastName="Bryant",CreatedOn=DateTime.Now,Roles=roles },
                 new User {Id=2,FirstName="Chris",LastName="Paul",CreatedOn=DateTime.Now,Roles=roles.Where(x=>x.Id==2).ToList() },
                 new User {Id=3,FirstName="Jerimy",LastName="Lin",CreatedOn=DateTime.Now,Roles=roles.Take(2).ToList() }
            };
        }
    }
}

 

姣好第二个指令和多少开首化配置后,我们举办第3个指令。

从数据库创立模型  

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

要从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上访问数据库萨姆pleDatabase。使用的提供程序是EntityFramework.MicrosoftSqlServer。这些NuGet包以及具备同等名称和统一图谋后缀的NuGet包必须增添到项目中。 

运作此命令后,能够见见DbContext派生类以及改动的模型类型。暗中同意景况下,模型的配备利用fluent API完毕。不过也足以将其改动为使用提供-a选项的数码演讲。还足以影响生成的上下文类名称以及出口目录。只需选用选取-h检查不一样的可用选项。

 

----------------未完待续

从数据库创建模型  

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

要从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检查不相同的可用选项。

 

----------------未完待续

3.2 Add-Migration Init -Verbose

实施此命令后,会在Migrations的文书夹中自动生成多个形如:时间戳_Init.cs的多寡迁移文件,如本例生成的是二〇一五12040507219_Init.cs那样一个文本名,个中Init是大家钦定的这次数据迁移的本子名称,文件中的内容如下:

 1 namespace EFRemoveManyToManyDemo.Migrations
 2 {
 3     using System;
 4     using System.Data.Entity.Migrations;
 5     
 6     public partial class Init : DbMigration
 7     {
 8         public override void Up()
 9         {
10             CreateTable(
11                 "dbo.Role",
12                 c => new
13                     {
14                         Id = c.Int(nullable: false, identity: true),
15                         Name = c.String(nullable: false, maxLength: 50),
16                     })
17                 .PrimaryKey(t => t.Id);
18             
19             CreateTable(
20                 "dbo.User",
21                 c => new
22                     {
23                         Id = c.Int(nullable: false, identity: true),
24                         FirstName = c.String(nullable: false, maxLength: 50),
25                         LastName = c.String(nullable: false, maxLength: 50),
26                         CreatedOn = c.DateTime(),
27                     })
28                 .PrimaryKey(t => t.Id);
29             
30             CreateTable(
31                 "dbo.LNK_User_Role",
32                 c => new
33                     {
34                         RoleId = c.Int(nullable: false),
35                         UserId = c.Int(nullable: false),
36                     })
37                 .PrimaryKey(t => new { t.RoleId, t.UserId })
38                 .ForeignKey("dbo.Role", t => t.RoleId, cascadeDelete: true)
39                 .ForeignKey("dbo.User", t => t.UserId, cascadeDelete: true)
40                 .Index(t => t.RoleId)
41                 .Index(t => t.UserId);
42             
43         }
44         
45         public override void Down()
46         {
47             DropForeignKey("dbo.LNK_User_Role", "UserId", "dbo.User");
48             DropForeignKey("dbo.LNK_User_Role", "RoleId", "dbo.Role");
49             DropIndex("dbo.LNK_User_Role", new[] { "UserId" });
50             DropIndex("dbo.LNK_User_Role", new[] { "RoleId" });
51             DropTable("dbo.LNK_User_Role");
52             DropTable("dbo.User");
53             DropTable("dbo.Role");
54         }
55     }
56 }

 

作者们得以因此这一个文件中的内容来看,有Up()和Down()那五个法子,Up()方法要实行的莫过于便是此番数据迁移要对数码实行的操作,而Down()方法则是在随后大家只要要退回到此版本应该实践的操作。

经过上述多个指令,如你焦灼地要去数据库管理工科具中查看有3个称作:ManyToManyRemove德姆o的数据库是不是已更改,那么很不满地告知你,还并未有。这时,大家还得实行最终二个发令来生成数据库和实体对应的表。

3.3 Update-Database -Verbose

奉行以上命令,大家那时候再张开数据库管理工科具。没有错ManyToManyRemove德姆o就在这边。再查看表是或不是成功生成呢,再检查一下表中是不是有我们开端化的多寡吧,没有错,这个都是足以部分。如何,欣喜吗,欢呼吧,大家做到了!!!

澳门新萄京官方网站 11

 

澳门新萄京官方网站 12

但还没完,请先过来平静,那还只是一个初始。Entity Framework还足以做得更加多,我们须求学习的也还会有很多,编制程序的征途平昔就不是一步到位的,得有个进程。一步一步往下看呢。

第四步、增、删、改、查操作

四.一 查询数据示例

展开大家项指标Program.cs文件。首先,大家来询问(Query)一下数据库中的数据,如下:

 1 static void Main(string[] args)
 2         {
 3             Query();
 4             ReadKey();
 5         }
 6 
 7         static void Query()
 8         {
 9             using (var cxt = new ManyToManyRemoveContext())
10             {
11                 var users = cxt.Users.ToList();
12                 users.ForEach(x =>
13                 {
14                     WriteLine("User First Name:{0},Last Name:{1},Create On:{2}n |__Roles:{3}", x.FirstName, x.LastName, x.CreatedOn, string.Join(",", x.Roles.Select(r => r.Name)));
15                 });
16             }
17         }

 

运作结果如图:

澳门新萄京官方网站 13

 

澳门新萄京官方网站 14

澳门新萄京官方网站:实体框架核心,全自动员搬迁移数据库的落到实处。肆.二 更新数据示例

再来更新一条数据库中的数据怎样,如下:

 1  static void Main(string[] args)
 2         {
 3             Update();
 4             Query();
 5             ReadKey();
 6         }
 7 
 8 static void Query()
 9         {
10             using (var cxt = new ManyToManyRemoveContext())
11             {
12                 var users = cxt.Users.ToList();
13                 users.ForEach(x =>
14                 {
15                     WriteLine("User First Name:{0},Last Name:{1},Create On:{2}n |__Roles:{3}", x.FirstName, x.LastName, x.CreatedOn, string.Join(",", x.Roles.Select(r => r.Name)));
16                 });
17             }
18         }
19 
20 static void Update()
21         {
22             using (var cxt = new ManyToManyRemoveContext())
23             {
24                 var user = cxt.Users.FirstOrDefault(x=>x.Id==3);
25                 user.FirstName = "ShuHao";
26                 cxt.SaveChanges();
27             }
28         }

 

运行结果如小编辈所料,如图:

澳门新萄京官方网站 15

 

澳门新萄京官方网站 16

4.三 删除数据示例

Id为三的User的FirstName已经从数据库更新了。同样的,大家要成功删除操作也正如简,如下:

1  static void Remove()
2         {
3             using (var cxt = new ManyToManyRemoveContext())
4             {
5                 var user = cxt.Users.FirstOrDefault(x=>x.Id==2);
6                 cxt.Users.Remove(user);
7                 cxt.SaveChanges();
8             }
9         }

 

4.肆 新添多少示例

就不再贴图了。最终是增添操作,向User表加多三个用户并分配一个Id为1的剧中人物,代码如下:

 1 static void Add()
 2         {
 3             List<Role> roles;
 4             using (var cxt = new ManyToManyRemoveContext())
 5             {
 6                 roles = cxt.Roles.ToList();
 7                 cxt.Users.Add(new User
 8                 {
 9                     Id = 4,
10                     FirstName = "Console",
11                     LastName = "App",
12                     CreatedOn = DateTime.Now,
13                     Roles = roles.Where(x => x.Id == 1).ToList()
14                 });
15             }
16         }

 

四.伍 删除多对绝大很多据的演示

好了,以上是对User(用户实体)举办轻易的增、删、改、查的操作,那么大家要贯彻多对多的删除操作呢?也便是删除用户的还要删除其对应的剧中人物,达成的代码如下:

 1 static void RemoveManyToMany()
 2         {
 3             using (var cxt = new ManyToManyRemoveContext())
 4             {
 5                 var user = cxt.Users.FirstOrDefault(x => x.Id == 1);
 6                 var roles = new List<Role>();
 7                 roles.AddRange(user.Roles.Select(x => x));
 8                 foreach (var role in roles)
 9                 {
10                     user.Roles.Remove(role);
11                 }
12                 cxt.Users.Remove(user);
13                 cxt.SaveChanges();
14             }
15         }

 

运维结果如图:

澳门新萄京官方网站 17

 

澳门新萄京官方网站 18

1体化示例代码及下载地址

好了,最终把Program.cs这几个测试文件贴上来,供参谋:

 1 using EFRemoveManyToManyDemo.Model;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using static System.Console;
 6 
 7 namespace EFRemoveManyToManyDemo
 8 {
 9     public class Program
10     {
11         static void Main(string[] args)
12         {
13             //Update();
14             WriteLine("Before many to many removed");
15             Query();
16             RemoveManyToMany();
17             WriteLine("After many to many removed");
18             Query();
19             ReadKey();
20         }
21 
22         static void Query()
23         {
24             using (var cxt = new ManyToManyRemoveContext())
25             {
26                 var users = cxt.Users.ToList();
27                 users.ForEach(x =>
28                 {
29                     WriteLine("User First Name:{0},Last Name:{1},Create On:{2}n |__Roles:{3}", x.FirstName, x.LastName, x.CreatedOn, string.Join(",", x.Roles.Select(r => r.Name)));
30                 });
31             }
32         }
33 
34         static void Add()
35         {
36             List<Role> roles;
37             using (var cxt = new ManyToManyRemoveContext())
38             {
39                 roles = cxt.Roles.ToList();
40                 cxt.Users.Add(new User
41                 {
42                     Id = 4,
43                     FirstName = "Console",
44                     LastName = "App",
45                     CreatedOn = DateTime.Now,
46                     Roles = roles.Where(x => x.Id == 1).ToList()
47                 });
48             }
49         }
50 
51         static void Update()
52         {
53             using (var cxt = new ManyToManyRemoveContext())
54             {
55                 var user = cxt.Users.FirstOrDefault(x => x.Id == 3);
56                 user.FirstName = "ShuHao";
57                 cxt.SaveChanges();
58             }
59         }
60 
61         static void Remove()
62         {
63             using (var cxt = new ManyToManyRemoveContext())
64             {
65                 var user = cxt.Users.FirstOrDefault(x => x.Id == 2);
66                 cxt.Users.Remove(user);
67                 cxt.SaveChanges();
68             }
69         }
70 
71         static void RemoveManyToMany()
72         {
73             using (var cxt = new ManyToManyRemoveContext())
74             {
75                 var user = cxt.Users.FirstOrDefault(x => x.Id == 1);
76                 var roles = new List<Role>();
77                 roles.AddRange(user.Roles.Select(x => x));
78                 foreach (var role in roles)
79                 {
80                     user.Roles.Remove(role);
81                 }
82                 cxt.Users.Remove(user);
83                 cxt.SaveChanges();
84             }
85         }
86     }
87 }

 

本文由澳门新萄京官方网站发布于www.8455.com,转载请注明出处:澳门新萄京官方网站:实体框架核心,全自动员

关键词: