qg777钱柜误乐

热门关键词: qg777钱柜误乐

EF CodeFirs 代码迁移、数据迁移

数据Curry面包车型地铁表,怎么着转为C#的类模型。如数据库表Test有2个字段idinttitlenvarchar(100State of Qatar有何工具得以将这么些表生成C#的类模型cs文件,如上面好像的代码test.cs

   近来悟出来三个道理,在这里时享受给大家:文凭代表你的千古,本领意味着你的明日,学习代表你的现在。

**译文,个人原创,转发请申明出处(C# 6 与 .NET Core 1.0 高端编制程序 - 38 章 实体框架主题(上卡塔尔(قطر‎),不对的地点款待建议与交换。** 

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

附Slovak语版原来的书文:Professional C# 6 and .NET Core 1.0 - 38 Entity Framework Core

本章节译文分为上下篇,下篇见: C# 6 与 .NET Core 1.0 高档编制程序 - 38 章 实体框架核心(下卡塔尔(قطر‎


本章内容

  • Entity Framework Core 1.0简介
  • 使用正视注入实体框架
  • 成立关系模型
  • 使用.NET CLI工具和MSBuild进行搬迁
  • 对象追踪
  • 履新目的和对象树
  • 冲突管理与立异
  • 运用工作

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

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

  • Books Sample
  • Books Sample with DI
  • Menus Sample
  • Menus with Data Annotations
  • Conflict Handling Sample
  • Transactions Sample 
publicclasstest{privateintid;publicint_id{get{returnid;}set{id=value;}}privatestringtitle;publicint_title{get{returntitle;}set{title=value;}}}

   十年河东十年河西,莫欺少年穷

实体框架的历史

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

因此日久天长对Entity Framework的为数相当的少修正,最新的版本是二个通通的重写。一齐来探访Entity Framework的野史,以致重写的从头到尾的经过。

  • Entity Framework 1—Entity Framework的首先个版本没有计划好与.NET 3.5合营,但它高效就足以与.NET 3.5 SP1包容。另二个产品LINQ to SQL提供了生机勃勃部分相像的效应,且早就可用于.NET 3.5。 LINQ to SQL和Entity Framework在超大程度上提供了相像的意义。LINQ to SQL更便于使用,但不能不用来访谈SQL Server。实体框架是遵照提供程序的,并提供了对两样关周到据库的会见。它包括更加多的功用,比如多对多映射而没有必要映射对象,n对n映射是唯恐的。 Entity Framework的一个缺陷是它的模型类型须求由EntityObject基类派生。将目的映射到事关选拔带有XML的EDMX文件完毕的。饱含的XML由四个形式组成:概念格局定义(CSD)定义具备其属性和事关的靶子类型;存款和储蓄情势定义(SSD)定义数据库表、列和涉及;以致映射形式语言(MSL)定义CSD和SSD怎么着相互映射。

  • Entity Framework 4—Entity Framework 4 在.NET 4中相称,並且拿到了要害改进,个中不少出自LINQ到SQL的主张。由于变化相当大,版本2和3已被跳过。那几个本子里扩展了延期加载以得到访谈属性的涉及。在应用SQL数据定义语言(DDL)设计模型之后,能够成立数据库。今后选拔Entity Framework的七个模型是Database First或Model First。大概最重大的风味是扶助简单对象类(POCO),由此不再要求从基类EntityObject派生。

随着更新(举个例子Entity Framework 4.1,4.2),NuGet包扩大了附加的作用,由此能越来越快地加上效果。 Entity Framework 4.1提供了Code First模型,个中用于定义映射的EDMX文件不再选用。相反,全部的照射都使用C#代码定义

  • 运用性质或Fluent API来定义的炫丽。

Entity Framework 4.3日增了对搬迁的支撑。有了那或多或少,就足以应用C#代码定义数据库结构的退换。使用数据库从应用程序自动应用数据库更新。

  • Entity Framework 5—Entity Framework 5的NuGet包辅助.NET 4.5和.NET 4应用程序。可是,Entity Framework 5的非常多功能都可用于.NET 4.5。 Entity Framework还是基于.NET 4.5在系统上安装的门类。此版本的新扩展效果与利益是性质订正以至帮衬新的SQL Server功效,比方空间数据类型。

  • Entity Framework 6—Entity Framework 6缓慢解决了Entity Framework 5的局部主题素材,个中部分是设置在系统上的框架的风流倜傥某个,黄金时代部分经过NuGet扩大提供。近些日子Entity Framework的全方位代码已移至NuGet包。为了不形成冲突,使用了三个新的命名空间。将应用程序移植到新本龙时,必得退换命名空间。

本书研讨Entity Framework的风靡版本,Entity Framework Core 1.0。此版本是二个剔除旧的一坐一起周密重写,不再辅助CSDL,SSDL和MSL的XML文件映射,只帮衬Code First - 使用Entity Framework 4.1丰硕的模子。Code First 并不意味着数据库无法先存在。您可以先创立数据库,也许仅从代码中定义数据库,以上三种接纳都以卓有效率的。

注意 Code First 这几个名称某个程度上令人误会。Code First 先创造代码或先数据库都以可行的。最先Code First的测验版本名称是Code Only。因为其余模型选项在称呼和浩特中学有First,所以“Code Only”的名号也被纠正。

Entity Framework 的左右逢源重写不仅仅支持关全面据库,还援救NoSql数据库 - 只必要三个提供程序。在撰文本文时,提供程序协助少数,但相信会任何时候间而扩展。 

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

Entity Framework Core 1.0不完全支持Entity Framework 6提供的具备功用。随着年华的推移,Entity Framework的新本子将提供更加的多效果与利益,留意所运用的Entity Framework的版本。纵然采用Entity Framework 6 比相当多强大的说辞,但在非Windows平台上应用ASP.NET Core 1.0、Entity Framework和通用Windows平台(UWP卡塔尔国,以致非关周密据存储,都须要使用Entity Framework Core 1.0。 

本章介绍Entity Framework Core 1.0。从贰个轻便易行的模型读取和SQL Server中写入新闻开头,稍后会介绍增多关系,在写入数据库时将介绍纠正追踪器和冲突处理。利用搬迁成立和改换数据库布局是本章的另四个关键部分。 

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

要么直接上边包车型客车也行。。

   学海无涯,精耕细作

实业框架简要介绍

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

在首先个示范中,首先成立数据库。能够动用Visual Studio 2014中的SQL Server对象能源微处理机实践此操作。选拔数据库实例(与Visual Studio一同安装的(localdb) MSSQLLocalDB),单击树视图中的数据库节点,然后采纳“增多新数据库”。示例数据库独有一个名称为Books的表。 

慎选Books数据库中的表节点,然后接收"增多新表"来创制表Books。使用图38.1中所示的设计器,恐怕经过在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
)
publicclasstest{publicintid;publicstringtitle;}

   标题叫EF CodeFirs 代码迁移、数据迁移。

创造模型 

用于访谈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类是二个轻易的实体类型,它定义了三个属性。 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; }
}

framework是2.0的,所以linq没搞。数据库MSSQLServer2008的,vs2013版本

   那么:到底叫代码迁移依然数据迁移?小编在网络看了大半天,怎么叫的都有,后来查了MSDN,MSDN上叫代码迁移。在那,大家也称之为代码迁移。

开创上下文 

始建的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);
  }
}

概念连接字符串的另三个取舍是接受依赖注入,将要本章后边介绍。 

   为啥有人将其称为数据迁移呢?只怕是因为本节内容和操作数据库有关<扩展一张表,删除一张表,扩张三个表字段,删除多个表字段,矫正三个表字段等>,所以网上亲密的朋友喻为数据迁移

写入数据库

方今已开立了有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对象财富微电脑查看写入到数据库的数码。

   MSDN等权威协会为什么称之为代码迁移呢?或者是因为本节的从头到尾的经过通过大家精通的C#代码就可以化解,所以称为代码迁移

从数据库读取

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

在调整时期展开AMDliTrace Events窗口,能够见到发送到数据库的SQL语句(必要Visual Studio 集团版):

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

Framework提供了一个LINQ提供程序,能够创建LINQ查询访谈数据库。能够利用如下所示语法的章程:

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

或采用LINQ查询语法:

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

采用那三种不一致的语法,都将发送下边的SQL语句到数据库:

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

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

   嘻嘻,上面是笔者的测度,人家可跳过

更新记录

只需改动已加载上下文的对象并调用SaveChangesAsync就能够轻易实现创新记录(代码文件Books萨姆ple / 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();
}

   正文:

除去记录

末段,让我们清理数据库并删除全体记录。能够透过查找全数记录并调用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语句删除全数实际不是逐个删除笔录。在第37章“ADO.NET”中解释了怎样变成那点。*

摸底了何等增加、查询、更新和删除记录,本章将介绍幕后的法力,并接受Entity Framework步入高级场景。

   背景:我们为啥要动用代码迁移?

运用正视注入  

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

要翻开此操作,Books萨姆pleWithDI示例项目对上二个代码示例项目张开了校勘。 

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

  依赖项

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

  命名空间

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

BooksContext类以往看起来很简短,只需定义Books属性(代码文件BooksSampleWithDI / BooksContext.cs):

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

BooksService是采用BooksContext的新类。BooksContext通过注入布局函数注入。方法AddBooksAsync和ReadBooks与上三个示范中的这个方法丰裕相仿,但她俩使用BooksService类的上下文成员,并非开创一个新的(代码文件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方法必要三个Action委托作为参数,个中选拔到三个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();
}

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

*注意 在第31章“XAML应用程序的方式”中读书有关注重注入和Microsoft.Framework.DependencyInjection包的越来越多音信,还是能够远瞻第40章“ASP.NET Core”和第41章“ ASP.NET MVC“。*

   大家利用CodeFirst开始化数据库无非以下三种办法:

创办模型  

本章的第三个示例映射单个表。第三个例证展现了创设表之间的涉嫌。在本节中使用C#代码创制数据库而并未有应用SQL DDL语句(或透过应用设计器)创制数据库。 

演示应用程序Menus萨姆ple使用以下信任项和命名空间:

  依赖项

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

   黄金年代、 每一回运营都会创建新的数据库

始建关系

让我们初阶创制二个模型。示例项目应用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);
  }
}

   Database.SetInitializer<XXXXXContext>(new DropCreateDatabaseAlways<XXXXXContext>());

使用.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方法列出了创制Menu卡德和菜单表所需的有着操作,包含主键、列和涉嫌。 Down方法删除多个表:

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

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

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

注意 正在张开的每一种更改都可以创建另七个搬迁。新搬迁仅定义从先前版本到新本子所需的改造。若是客户的数据库须要从随机开始的一段时期的版本更新,迁移数据库时调用必要的动员搬迁。 

在支付进度中,也行无需全数的迁徙,恐怕要求从种类中开创,因为恐怕未有该类有的时候气象的数据仓库储存在。在这种情景下能够去除迁移并创立叁个超大的新搬迁。

   二、唯有首先次运营~才会成立新的数据库~暗许的主意

选拔MSBuild举办搬迁  

假定你正在选拔基于MSBuild的项目Entity Framework迁移并不是DNX,迁移命令是不相同的。使用完整框架调控台应用程序、WPF应用程序或ASP.NET 4.6档案的次序项目,必要在NuGet包微处理机调整新北内定迁移命令,实际不是开拓职员命令提醒符。从Visual Studio通过 工具➪库管理器控制台➪包微处理器调控台 运转包微处理器调节台。

在包微处理机调控台能够选拔PowerShell脚本加多和删除迁移。命令如下

> Add-Migration InitMenuCards

始建三个Migrations文件夹,此中包括如前所示的迁移类。

创制数据库 

趁着迁移类型形成,能够创制数据库。 DbContext派生类MenusContext包括多少个回来DatabaseFacade对象的Database属性。使用DatabaseFacade能够创设和删除数据库。即使数据库不设有,EnsureCreated方法会成立数据库;假如数据库已存在,则不施行其它操作。方法EnsureDeletedAsync删除数据库。以下代码片段创制数据库(假若它空中楼阁)(代码文件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表定义了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 列的分寸能够从NVARCHA凯雷德(MAX)减小,SQL Server定义了可用于Price列的Money类型,况且组织名称能够从dbo改进。 Entity Framework提供了八个选项从代码中执行那几个更动:数据证明和Fluent API,上边将钻探。

数量解说

影响生成的数据库的黄金年代种办法是向实体类型丰硕数据注释。能够动用Table属性改革表的称谓。要改成布局名称,Table属性定义Schema属性。如若要为字符串类型钦定不一致的长度,能够应用MaxLength属性(代码文件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和MaxLength属性同样能够动用。使用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
);

   Database.SetInitializer<XXXXXContext>(new CreateDatabaseIfNotExists<XXXXXContext>());

Fluent API  

潜濡默化成立的表的另风度翩翩种艺术是利用Fluent API中DbContext派生类的OnModelCreating方法。它的亮点是足以维持实体类型大约,而不加多任何性质,Fluent API还提供了比接受品质更多的选项。 

以下代码片段呈现了BooksContext类重写OnModelCreating方法。作为参数采纳的ModelBuilder类提供了一些方法,并定义了二种扩充方法。 HasDefaultSchema是内部四个扩展方法,它将暗中同意布局接受于方今颇有类型的模子。 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定义映射方法去定义意气风发对多映射。HasMany 结合 WithOne 方法定义了多Menus 和一个Menu Card 的映照。 HasMany供付与WithOne链接,即HasOne方法必要一个带WithMany或WithOne的链。链接 HasOne 和 WithMany定义了豆蔻年华对多关系,链接HasOne与WithOne定义了卓越的关系:

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

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

在OnModelCreating方法中开创映射之后方可创设如前所示的动员搬迁。

   三、 更改模型后~运行~会创立新的数据库

从数据库创制模型  

从模型可以成立数据库,相反从数据库也足以创造模型。 

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

 

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

   Database.SetInitializer<XXXXXContext>(new DropCreateDatabaseIfModelChanges<XXXXXContext>());

   不论大家应用哪一类办法,当法则建马上,都会成立新的数据库,而创设新的数据库就意味着‘重新再来’

   举个例证:若是您的团队开拓的门类早已被顾客利用,客商在骨子里的临蓐操作中早已成立了好多数量,尽管,某一天顾客改过必要,大家难不成要利用上述办法将数据库重新建立?风姿浪漫旦重新建立,客商早前的数目就能够吐弃,那是别的二个顾客不能够耐受的

   为领悟决那么些难点,大家要引进代码迁移

   在举办代码迁移早先,大家亟须办好数据库备份专门的事业,确认保障客户数量的安全性及完整性

   以往我们引进数据迁移示例:

   我们有以下模型类:

   Student模型类

    public class Student
    {
        [Key]
        public int Id { get; set; }
        [Required]
        [StringLength(10)]
        public string Name { get; set; }//姓名
        [StringLength(2)]
        public string Sex { get; set; }//性别
        [Unique(ErrorMessage="学号不允许重复")]
        [StringLength(18)]
        public string StudentNum { get; set; }//学号

        [StringLength(100)]
        public string StudentAddress { get; set; }//地址
    }

   Course模型类

    public class Course
    {
        [Key]
        public int Id { get; set; }
        [Required]
        [StringLength(20)]
        public string Name { get; set; }//课程名称
     }

   Score模型类

        [Key]
        public int Id { get; set; }

        public int StudentScore { get; set; }//学生分数

        public int StudentID { get; set; }//学生ID

        public int CourseID { get; set; }//课程ID

        public virtual Student Student { get; set; }//virtual关键字修饰,用于延迟加载 提高性能 只有显式调用时 才会加载 并可以代表一个Student对象 也就是 属性==对象

        public virtual Course Course { get; set; }//virtual关键字修饰,用于延迟加载 提高性能 只有显式调用时  才会加载 并可以代表一个Course对象 也就是 属性==对象

   StudentContext上下文

    public class StudentContext : DbContext
    {
        public StudentContext()
            : base("StudentContext")//指定连接字符串
        {

        }
        public DbSet<Student> Students { get; set; }
        public DbSet<Course> Courses { get; set; }
        public DbSet<Score> Scores { get; set; }
        /// <summary>
        /// OnModelCreating方法中的modelBuilder.Conventions.Remove语句禁止表名称正在多元化。如果你不这样做,所生成的表将命名为Students、Courses和Enrollments。相反,表名称将是Student、Course和Enrollment。开发商不同意关于表名称应该多数。本教程使用的是单数形式,但重要的一点是,您可以选择哪个你更喜欢通过包括或省略这行代码的形式。
        /// </summary>
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }

   现在顾客提议如下要求:在作保数据完整性的情状下,增加一张高校表<字段:高校名称、高校地址,学园热线>及扩大学生联系格局字段

   首先,大家增多学园模型类:

    public class School//新建一张学校表-----------------------------新建的表
    {
        [Key]
        public int schoolId { get; set; }
        [Required]
        [StringLength(10)]
        public string schoolName { get; set; }//学校名称

        [StringLength(100)]
        public string StudentAddress { get; set; }//学校地址

        [StringLength(20)]
        public string StudentTel { get; set; }//学校热线
    }

   更正学子模型类如下:

    public class Student
    {
        [Key]
        public int Id { get; set; }
        [Required]
        [StringLength(10)]
        public string Name { get; set; }//姓名
        [StringLength(2)]
        public string Sex { get; set; }//性别
        [Unique(ErrorMessage="学号不允许重复")]
        [StringLength(18)]
        public string StudentNum { get; set; }//学号

        [StringLength(100)]
        public string StudentAddress { get; set; }//地址

        [StringLength(11)]
        public string StudentTel { get; set; }//联系电话----------------------------新加的字段
    }

  上下文类加上DBset<School>如下:

本文由qg777发布于操作系统,转载请注明出处:EF CodeFirs 代码迁移、数据迁移

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。