迁移错误:

今天在使用EF6 Code First时,出现如下错误,折腾了老半天。分享一下,帮后面的兄弟少走弯路。

PM> Enable-Migrations
Checking if the context targets an existing database...
使用“8”个参数调用“CreateInstanceFrom”时发生异常:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
所在位置 E:\....\src\packages\EntityFramework.6.1.3\tools\EntityFramework.psm1:809 字符: 31
+     $domain.CreateInstanceFrom <<<< (+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException+ FullyQualifiedErrorId : DotNetMethodTargetInvocation

出现这个的原因是因为:Model项目中的EntityFrameWork的版本,和其它的项目版本不一致造成的。统一改成一样的重新编译一切正常。

本演练将提供对实体框架中 Code First 迁移的概述。您可以完成整个演练,也可以跳至自己感兴趣的主题。主题如下:

  • 启用迁移
  • 生成并运行迁移
  • 自定义迁移
  • 数据移动和自定义 SQL
  • 迁移到特定版本(包括降级)
  • 生成 SQL 脚本
  • 在应用程序启动时自动升级(MigrateDatabaseToLatestVersion 初始值设定项)

构建一个初始模型和数据库

在我们开始使用迁移之前,需要有一个项目和一个 Code First 模型。对于本次演练任务,我们仍将使用 Blog 和 Post 规范模型。

  • 创建新的 MigrationsDemo 控制台应用程序
  • 将最新版本的 EntityFramework NuGet 包添加到项目
    • 工具 –> 库程序包管理器 –> 程序包管理器控制台
    • 运行 Install-Package EntityFramework 命令
  • 添加一个包含下面所示代码的 Model.cs 文件。这段代码定义一个 Blog 类,该类由我们的域模型和一个作为 EF Code First 上下文的 BlogContext 类组成。
using System.Data.Entity; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data.Entity.Infrastructure; 

namespace MigrationsDemo {     public class BlogContext : DbContext     {         public DbSet<Blog> Blogs { get; set; }     } 

    public class Blog     {         public int BlogId { get; set; }         public string Name { get; set; }     } }

  • 现在我们已经有了一个模型,该使用它来执行数据访问了。用下面所示代码更新 Program.cs 文件。
using System; using System.Collections.Generic; using System.Linq; using System.Text; 

namespace MigrationsDemo {     class Program     {         static void Main(string[] args)         {             using (var db = new BlogContext())             {                 db.Blogs.Add(new Blog { Name = "Another Blog " });                 db.SaveChanges(); 

                foreach (var blog in db.Blogs)                 {                     Console.WriteLine(blog.Name);                 }             } 

            Console.WriteLine("Press any key to exit...");             Console.ReadKey();         }     } }

  • 运行应用程序,您会看到已为您创建 MigrationsCodeDemo.BlogContext 数据库。

    如果安装了 SQL Express(包括在 Visual Studio 2010 中),则该数据库将在本地 SQL Express 实例(.\SQLEXPRESS)中创建。如果未安装 SQL Express,则 Code First 将尝试使用 LocalDb ((localdb)\v11.0) - LocalDb 包括在 Visual Studio 2012 中。

    注意:如果安装有 SQL Express,则始终优先使用它,即使您在使用 Visual Studio 2012 也是如此


    (LocaDb 数据库)


    (SQL Express 数据库)

启用迁移

现在要对我们的模型进行一些更改。

  • 让我们向 Blog 类引入一个 Url 属性。
public string Url { get; set; }

如果您打算再次运行该应用程序,则将显示 InvalidOperationException,表明支持“BlogContext”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库 ( http://go.microsoft.com/fwlink/?LinkId=238269)。

按异常消息指示,现在应该开始使用 Code First 迁移。第一步是为上下文启用迁移。

  • 在程序包管理器控制台中运行 Enable-Migrations 命令

此命令已为项目添加了 Migrations 文件夹,此新文件夹包含两个文件:

  • Configuration 类。此类允许您针对上下文配置迁移的行为。对于此演练,我们将使用默认配置。
    因为在您的项目中只有一个 Code First 上下文,所以 Enable-Migrations 已自动填入要应用此配置的上下文类型中。
  • InitialCreate 迁移。此迁移已在启用迁移之前生成,因为我们事先让 Code First 自动创建了一个数据库。此基架迁移中的代码表示数据库中已创建的对象。在本例中,此类对象为 Blog 表,其中包含 BlogId 和 Name 列。文件名包含时间戳,这对于排序十分有帮助。
    如果尚未创建数据库,则不会将此 InitialCreate 迁移添加到项目中。而是,首次调用 Add-Migration 时,用于创建这些表的代码将为新迁移搭建基架。

生成并运行迁移

Code First 迁移有两个主命令,下面您将会熟悉它们。

  • Add-Migration 将根据自创建上次迁移以来您对模型所做的更改,为下一次迁移搭建基架。
  • Update-Database 将所有挂起的迁移应用于数据库。

我们需要为迁移搭建基架以处理先前添加的新 Url 属性。使用 Add-Migration 命令可以为这些迁移指定名称,我们将其称为 AddBlogUrl

  • 在程序包管理器控制台中运行 Add-Migration AddBlogUrl 命令。
  • 在 Migrations 文件夹中,现在有了新的 AddBlogUrl 迁移。该迁移文件名以时间戳作为前缀,这对于排序十分有帮助。
namespace MigrationsDemo.Migrations {     using System;     using System.Data.Entity.Migrations; 

    public partial class AddBlogUrl : DbMigration     {         public override void Up()         {             AddColumn("Blogs", "Url", c => c.String());         } 

        public override void Down()         {             DropColumn("Blogs", "Url");         }     } }

现在,我们可以编辑此迁移或向其添加内容,一切都很不错。让我们使用 Update-Database 将此迁移应用于数据库。

  • 在程序包管理器控制台中运行 Update-Database 命令。
  • Code First 迁移将对 Migrations 文件夹中的迁移与已应用于数据库的迁移进行比较。它将了解到需要应用 AddBlogUrl 迁移,于是便运行该迁移。

此时,MigrationsDemo.BlogContext 数据库已进行了更新,其 Blogs 表中包含了 Url 列。

自定义迁移

到目前为止,我们生成并运行了迁移,而未进行任何更改。现在,让我们看一下如何编辑默认情况下生成的代码。

  • 我们需要对模型再进行一些更改,让我们向 Blog 类添加一个新的 Rating 属性。
public int Rating { get; set; }

  • 再添加一个新的 Post 类
public class Post {     public int PostId { get; set; }     [MaxLength(200)]     public string Title { get; set; }     public string Content { get; set; } 

    public int BlogId { get; set; }     public Blog Blog { get; set; } }

  • 我们还要向 Blog 类添加一个 Posts 集合,以在 Blog 与 Post 之间形成另一层关系。
public virtual List<Post> Posts { get; set; }

我们将使用 Add-Migration 命令让 Code First 迁移自动在迁移时为其最佳猜测搭建基架。我们将此迁移称为 AddPostClass

  • 在程序包管理器控制台中运行 Add-Migration AddPostClass 命令。

Code First 迁移为这些更改搭建基架的工作做得很好,但有些内容可能需要我们更改:

  1. 首先,我们向 Posts.Title 列添加一个唯一索引
    (添加到以下代码的第 22 和 29 行)。
  2. 还添加一个不可为 Null 的 Blogs.Rating 列。如果表中有任何现有数据,则这些数据将被分配采用新列数据类型的 CLR 默认值(Rating 为整数,因此默认值将为 0)。但我们想指定默认值 3,为 Blogs 表中的现有行设置一个还不错的起始等级。
    (您可以在以下代码的第 24 行看到指定的默认值)
namespace MigrationsCodeDemo.Migrations {     using System;     using System.Data.Entity.Migrations; 

    public partial class AddPostClass : DbMigration     {         public override void Up()         {             CreateTable(                 "Posts",                 c => new                     {                         PostId = c.Int(nullable: false, identity: true),                         Title = c.String(maxLength: 200),                         Content = c.String(),                         BlogId = c.Int(nullable: false),                     })                 .PrimaryKey(t => t.PostId)                 .ForeignKey("Blogs", t => t.BlogId, cascadeDelete: true)                 .Index(t => t.BlogId)                 .Index(p => p.Title, unique: true); 

            AddColumn("Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3));         } 

        public override void Down()         {             DropIndex("Posts", new[] { "Title" });             DropIndex("Posts", new[] { "BlogId" });             DropForeignKey("Posts", "BlogId", "Blogs");             DropColumn("Blogs", "Rating");             DropTable("Posts");         }     } }

我们编辑好的迁移已准备就绪,让我们使用 Update-Database 更新数据库。这次指定 –Verbose 标记,以便您能够看见 Code First 迁移所运行的 SQL。

  • 在程序包管理器控制台中运行 Update-Database –Verbose 命令。

数据移动/自定义 SQL

到目前为止,我们了解了不更改或迁移任何数据的迁移操作,现在看一下需要来回移动一些数据的迁移操作。目前还没有为数据移动提供本机支持,但我们可以在脚本中的任何位置运行一些任意 SQL 命令。

  • 现在向模型中添加一个 Post.Abstract 属性。随后,我们将使用 Content 列开头的一些文本为现有文章预填充 Abstract
public string Abstract { get; set; }

我们将使用 Add-Migration 命令让 Code First 迁移自动在迁移时为其最佳猜测搭建基架。

  • 在程序包管理器控制台中运行 Add-Migration AddPostAbstract 命令。
  • 生成的迁移负责处理架构更改,但我们还希望使用每篇文章内容的前 100 个字符预填充 Abstract 列。为此,可以向下拖到 SQL 并在添加该列后运行 UPDATE 语句。
    (添加到以下代码的第 12 行)。
namespace MigrationsCodeDemo.Migrations {     using System;     using System.Data.Entity.Migrations; 

    public partial class AddPostAbstract : DbMigration     {         public override void Up()         {             AddColumn("Posts", "Abstract", c => c.String()); 

            Sql("UPDATE Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");         } 

        public override void Down()         {             DropColumn("Posts", "Abstract");         }     } }

我们编辑好的迁移很不错,让我们使用 Update-Database 更新数据库。我们将指定 –Verbose 标记,以便可以查看正在对数据库运行的 SQL。

  • 在程序包管理器控制台中运行 Update-Database –Verbose 命令。

迁移到特定版本(包括降级)

到目前为止,我们一直是升级到最新迁移,但有时您可能需要升级/降级到特定迁移。

假如我们希望将数据库迁移到当时运行 AddBlogUrl 迁移后所处的状态。可以使用 –TargetMigration 开关降级到此迁移。

  • 在程序包管理器控制台中运行 Update-Database –TargetMigration: AddBlogUrl 命令。

此命令将为 AddBlogAbstract 和 AddPostClass 迁移运行 Down 脚本。

如果要一直回滚到空数据库,可以使用 Update-Database –TargetMigration: $InitialDatabase 命令。

获取 SQL 脚本

假如其他开发人员的计算机上也需要这些更改,则在我们将所做的更改签入源代码管理后,他们只需执行同步操作即可。在他们得到我们的新迁移后,即可运行 Update-Database 命令在本地应用这些更改。不过,如果希望将这些更改推送到测试服务器并最终应用于生产,我们可能希望向 DBA 提交一个 SQL 脚本。

  • 运行 Update-Database 命令,但此时指定 –Script 标记,使更改写入脚本而不应用。我们还将指定为其生成脚本的源和目标迁移。我们希望脚本用于从空数据库 ($InitialDatabase) 最新版本(迁移 AddPostAbstract)的迁移。
    如果不希望指定目标迁移,迁移将使用最新迁移作为目标。如果未指定源迁移,迁移将使用数据库的当前状态。
  • 在程序包管理器控制台中运行 Update-Database -Script -SourceMigration: $InitialDatabase -TargetMigration: AddPostAbstract 命令。

Code First 迁移将运行迁移管道,而不是实际应用更改,它会自动将更改写出到一个 .sql 文件。生成脚本后,将会自动在 Visual Studio 中打开它,以供您查看或保存。

在应用程序启动时自动升级(MigrateDatabaseToLatestVersion 初始值设定项)

如果您要部署应用程序,可能希望在应用程序启动时自动升级数据库(通过应用所有挂起的迁移)。可通过注册 MigrateDatabaseToLatestVersion 数据库初始值设定项来实现这一点。数据库初始值设定项只是包含用于确保数据库安装正确的某种逻辑。首次在应用程序进程 (AppDomain) 中使用上下文时,将运行此逻辑。

我们可以更新 Program.cs 文件(如下所示),先设置 BlogContext 的 MigrateDatabaseToLatestVersion 初始值设定项,然后再使用上下文(第 14 行)。请注意,您还需要为 System.Data.Entity 命名空间添加一个 using 语句(第 5 行)。

创建此初始值设定项的实例时,需要指定上下文类型 (BlogContext) 和迁移配置 (Configuration) - 迁移配置是启用迁移时添加到 Migrations 文件夹的类。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Entity; using MigrationsDemo.Migrations; 

namespace MigrationsDemo {     class Program     {         static void Main(string[] args)         {             Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogContext, Configuration>()); 

            using (var db = new BlogContext())             {                 db.Blogs.Add(new Blog { Name = "Another Blog " });                 db.SaveChanges(); 

                foreach (var blog in db.Blogs)                 {                     Console.WriteLine(blog.Name);                 }             } 

            Console.WriteLine("Press any key to exit...");             Console.ReadKey();         }     } }

现在,每次应用程序运行时,它都会先检查所面向的数据库是否是最新的;如果不是,便会应用所有挂起的迁移。

来源:https://msdn.microsoft.com/zh-cn/data/jj591621(v=vs.113).aspx

转载于:https://www.cnblogs.com/wgale025/p/6223328.html

Code First 迁移,及迁移错误相关推荐

  1. mysql迁移时出现错误:INFO [alembic.runtime.migration] Context impl MySQLImpl. INFO [alembic.runtime.migrat

    mysql迁移时出现错误:INFO [alembic.runtime.migration] Context impl MySQLImpl. INFO [alembic.runtime.migrat 我 ...

  2. Pytorch模型迁移和迁移学习,导入部分模型参数

    Pytorch模型迁移和迁移学习 目录 Pytorch模型迁移和迁移学习 1. 利用resnet18做迁移学习 2. 修改网络名称并迁移学习 3.去除原模型的某些模块 1. 利用resnet18做迁移 ...

  3. 迁移学习 迁移参数_迁移学习简介

    迁移学习 迁移参数 介绍 (Introduction) We as humans have the ability to transfer the knowledge gained in one ta ...

  4. 软件测试-PR录制脚本程序的时候出现license invalid,error code=-13或者-24的错误

    如果你在使用PR录制脚本程序的时候出现license invalid,error code=-13或者-24的错误 那么证明你没有许可证,需要联络泽众公司那边,申请许可证 有关操作见下: http:/ ...

  5. KVM 虚拟机在物理主机之间迁移的实现 -- 静态迁移/动态迁移/存储迁移

    原文转自:http://www.ibm.com/developerworks/cn/linux/l-cn-mgrtvm2/ 静态迁移 静态迁移:也叫做常规迁移.离线迁移(Offline Migrati ...

  6. mysql 热迁移,proxmox迁移详解

    转载来自51cto:https://blog.51cto.com/15082392/2656486 proxmox迁移详解 骚年 运维少年 proxmox 迁移详解 一.迁移概述 迁移,顾名思义,即将 ...

  7. Gitea 无法启动提示 (code=exited, status=203/exec) 错误

    完整的提示信息为: ● gitea.service - Gitea (Git with a cup of tea) Loaded: loaded (/etc/systemd/system/gitea. ...

  8. 微信公众平台如何操作迁移?迁移公证步骤是什么?

    微信公众平台,一对多传播,信息高达到率.通过这一平台,个人和企业都可以打造一个微信公众号,并实现和特定群体的文字.图片.语音的全方位沟通与互动.微信公众平台是企业进行业务推广的一种有力途径.微信公众平 ...

  9. (fuel)openstack 冷迁移+热迁移

    前言:在已经搭建好的openstack上进行虚拟机迁移,在此之前需要先创建一个虚拟机实例,具体创建过程自行百度(随便创建一下就好了,作为demo也不需要这个实例能联网啥的),参考博客openstack ...

最新文章

  1. Eclipse 小插件
  2. 多人开源博客系统再搜集
  3. 将excel的数据导入到mysql数据表
  4. MATLAB机器学习系列-3:BP神经网络算例实现
  5. mysql 中有没有临时表_MySQL 中的两种临时表
  6. Editor扩展之查看Prefab用在那儿
  7. java二次指数平滑法预测未来的值
  8. C++设计模式解析之单例模式解析
  9. 1.node.js 概述
  10. 学习机器学习,需要具备什么的数学基础?
  11. SHP格式数据点线面无边界坐标生成经纬度边界点集合数据
  12. 微信小程序名称、简称设置规范
  13. 有了域名空间服务器怎么做网站,有了域名和空间怎么建网站?
  14. 利用谷歌搜索建立自己的站内搜索引擎
  15. 设置用户计算机的ip地址,电脑动态IP地址怎么设置
  16. 如何用VBA制作工资条
  17. 编程题走迷宫_编程题——机器人走迷宫 (用C语言)
  18. HTML基础之 HTML5新增视频和音频标签
  19. nodejs无法下载puppeteer附带的chromium解决方案
  20. WPS office文档 为何输入文字不显示

热门文章

  1. 分类整理我在SF上针对某些问题作的回答
  2. Centos YUM国内163源
  3. Android1 按钮
  4. 基于 C++ POCO 库封装的异步多线程的 CHttpClient 类
  5. 开源的人品测试机 (windows版)
  6. 通过多组的HSRP实现网络的冗余和负载
  7. encoder decoder模型_3分钟|聊一聊 Decoder 模块
  8. python的函数代码块_Python从菜鸟到高手(8):print函数、赋值与代码块
  9. linux做完sftp端口分离后ftp,Linux 中实现文件传输服务(FTP、SFTP)
  10. svpwm仿真_【好物推荐】《现代永磁同步电机控制原理及MATLAB仿真》