EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)

原文地址:Code First Migrations and Deployment

原文主要讲两部分:开发环境下数据库迁移到其他数据库服务器;以及在Azure上如何部署应用;

迁移数据库

原文前面讲一堆内容,主要就是说数据库在开发过程中,如果数据模型经常需要调整,那么数据库每次都删除重建有点不太现实;尤其是对于已部署的正式环境,需要的仅仅是数据库升级,而不可能直接Drop掉,再重新Create.

所以,需要启用EF的数据迁移功能。

原文为了演示效果更好,就直接演示了迁移升级到一个全新的数据库中:

第1步:把Web.config文件中 entityFramework节点下 contexts注释掉:

  <entityFramework>
    <!--<contexts>
      <context type="EFTest.DAL.SchoolContext, EFTest">
        <databaseInitializer type="EFTest.DAL.SchoolInitializer, EFTest" />
      </context>
    </contexts>-->
    <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>

第2步:数据库连接字符串中,数据库名改个名字,比如EFTest2

<connectionStrings>
    <add name="SchoolContext" connectionString="Data Source=(localdb)\ProjectsV13;Initial Catalog=EFTest2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;" providerName="System.Data.SqlClient" />
  </connectionStrings>

第3步:打开PM控制台:

第4步: 先执行 enable-migrations , 会创建一个Migrations子目录,并多出一个Configuration.cs文件;

再执行 add-migration InitialCreate , 会在Migrations子目录创建一个带时间戳的 xxxxxxxxxx_InitialCreate文件;

第5步,在Configuration.cs文件 有个Seed方法就是用来初始化数据库的时候放入的种子数据; 可以如以下方式加入数据:

在这个要注意,Seed方法在后面执行update-database命令的时候会被执行,而且每次执行update-database命令的时候都会执行;

所以这个地方需要用AddOrUpdate来处理一些种子数据,防止插入重复数据;

另外,注意一些外键数据,例如是数据库自增长的列,则需要前面先保存的数据到数据库,然后才用ID这属性值(不然ID是没数据的)

namespace EFTest.Migrations
{
    using Models;
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<EFTest.DAL.SchoolContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }

        protected override void Seed(EFTest.DAL.SchoolContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //

            var students = new List<Student>
            {
                new Student { FirstMidName = "Carson",   LastName = "Alexander",
                    EnrollmentDate = DateTime.Parse("2010-09-01") },
                new Student { FirstMidName = "Meredith", LastName = "Alonso",
                    EnrollmentDate = DateTime.Parse("2012-09-01") },
                new Student { FirstMidName = "Arturo",   LastName = "Anand",
                    EnrollmentDate = DateTime.Parse("2013-09-01") },
                new Student { FirstMidName = "Gytis",    LastName = "Barzdukas",
                    EnrollmentDate = DateTime.Parse("2012-09-01") },
                new Student { FirstMidName = "Yan",      LastName = "Li",
                    EnrollmentDate = DateTime.Parse("2012-09-01") },
                new Student { FirstMidName = "Peggy",    LastName = "Justice",
                    EnrollmentDate = DateTime.Parse("2011-09-01") },
                new Student { FirstMidName = "Laura",    LastName = "Norman",
                    EnrollmentDate = DateTime.Parse("2013-09-01") },
                new Student { FirstMidName = "Nino",     LastName = "Olivetto",
                    EnrollmentDate = DateTime.Parse("2005-08-11") }
            };
            students.ForEach(s => context.Students.AddOrUpdate(p => p.LastName, s));
            context.SaveChanges();

            var courses = new List<Course>
            {
                new Course {CourseID = 1050, Title = "Chemistry",      Credits = 3, },
                new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3, },
                new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3, },
                new Course {CourseID = 1045, Title = "Calculus",       Credits = 4, },
                new Course {CourseID = 3141, Title = "Trigonometry",   Credits = 4, },
                new Course {CourseID = 2021, Title = "Composition",    Credits = 3, },
                new Course {CourseID = 2042, Title = "Literature",     Credits = 4, }
            };
            courses.ForEach(s => context.Courses.AddOrUpdate(p => p.Title, s));
            context.SaveChanges();

            var enrollments = new List<Enrollment>
            {
                new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Alexander").ID,
                    CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
                    Grade = Grade.A
                },
                 new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Alexander").ID,
                    CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
                    Grade = Grade.C
                 },
                 new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Alexander").ID,
                    CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
                    Grade = Grade.B
                 },
                 new Enrollment {
                     StudentID = students.Single(s => s.LastName == "Alonso").ID,
                    CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
                    Grade = Grade.B
                 },
                 new Enrollment {
                     StudentID = students.Single(s => s.LastName == "Alonso").ID,
                    CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
                    Grade = Grade.B
                 },
                 new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Alonso").ID,
                    CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
                    Grade = Grade.B
                 },
                 new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Anand").ID,
                    CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
                 },
                 new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Anand").ID,
                    CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
                    Grade = Grade.B
                 },
                new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
                    CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
                    Grade = Grade.B
                 },
                 new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Li").ID,
                    CourseID = courses.Single(c => c.Title == "Composition").CourseID,
                    Grade = Grade.B
                 },
                 new Enrollment {
                    StudentID = students.Single(s => s.LastName == "Justice").ID,
                    CourseID = courses.Single(c => c.Title == "Literature").CourseID,
                    Grade = Grade.B
                 }
            };

            foreach (Enrollment e in enrollments)
            {
                var enrollmentInDataBase = context.Enrollments.Where(
                    s =>
                         s.Student.ID == e.StudentID &&
                         s.Course.CourseID == e.CourseID).SingleOrDefault();
                if (enrollmentInDataBase == null)
                {
                    context.Enrollments.Add(e);
                }
            }
            context.SaveChanges();
        }
    }
}

带时间戳的 xxxxxxxxxx_InitialCreate文件本次不需要自己调整,主要包含了Up和Down 方法;

Up用来升级数据库;Down用来恢复数据库;

第6步:在PM控制台输入 update-database 进行数据升级(本次是新建一个新数据库EFTest2 并新建表,并插入种子数据)

 

部署至 Azure

后面部分原文采用的是国际版的Azure,并且是经典管理页面,后面本人将采用国内世纪互联版Azure以及新的资源组管理页面来测试部署应用;

前提条件:需要有世纪互联运营的中国区Azure订阅账号!

www.portal.azure.cn 用订阅账号登录。

步骤1:先新建一个资源组用来进行综合管理项目下属的Azure资源(如 App Service , SQL DB, 或者以后Blob 存储等)

步骤2:建SQL Server 数据库,本次先用SQL Server 测试;(Azure也支持MySQL)

 

先输入数据库名称,选择第1步创建好的资源组;点击配置Server,在右页点击新建一个Server (如果已经有DB Server ,可以直接选择,一个Server上可以多个DB实例)

如果是新建的Server ,需要输入Server Name ,以及设置访问的账号及密码;选择区域,人在上海,所以选择东区;

默认的数据库规格有点高,测试就用最小的规格就可以。。。选择Price Tier 改为 5DTU 2GB

点击Create后,等创建结束即可;可以点击刷新按钮看下:

步骤3:数据库新建后,就可以做次数据库迁移;

在做数据库迁移之前,需要设置Azure的数据库可以被本地的IP地址访问到:

点击选中SQL 数据库,在Overview的右页点击 Set Server firewall

不需要自己去查自己的外网IP地址是多少,已经自动帮你列好,只要点上面的Add client IP按钮即可:

千万记得点 Save

获取连接字符串:

把拷贝的数据库连接字符串粘贴到应用的Web.Config

(请把账号和密码填进去。。。。。不要忘记了)

然后直接在PMC输入 update-database

步骤4:新建App Service

选择Web App:

一堆废话就不看了,点创建按钮:

输入AppName,选择资源组,点击App Service plan/Location 按钮,在右页点击Create New:

输入App Service Plan Name ,选择区域,点击Prcing tier ,选择B1 Basic (最便宜,测试嘛,能省则省)

选好后,点创建按钮:

一般几分钟后,就能创建成功;

步骤5: 设置VS2017可以访问中国版Azure :

参考:

https://docs.azure.cn/zh-cn/articles/others/aog-portal-management-qa-vs2017-login

步骤6:发布应用

VS2017登录成功后,可以在Server Explorer里看到自己的Azure订阅,以及订阅下面的所有资源;

邮件点击项目发布后,选择发布到MS Azure App Service , 并点选Select Existing ,然后点Publish按钮:

选择准备发布的App Serivce ,然后点 Ok按钮:

Output窗口输出结果:

成功后,会自动启动浏览器打开网页: