构建MySql的ASP.NET MVC5应用的演练(一)

来源:互联网 发布:激战2捏脸数据图表 编辑:程序博客网 时间:2024/05/06 00:40

 

构建MySql的ASP.NET MVC5应用的演练(一)

 

 

1 概述


 

 

目标:第一、使用MySql数据库,建立一个使用构建MySqlASP.NET MVC5应用的演练的应用,实现用户和角色管理,身份验证的数据库为指定的MySql数据库,用EF Code First实现迁移。第二、使用“来自数据库的Code First”的方式对现有的数据库表新建ADO.NET实体数据模型,用EF Code First实现迁移,根据模型生成CRUD页面。

要点:使用MySql.Data.Entity。在一个项目中使用多个上下文进行迁移。

需要的软件:Visual Studio 2015 MySql 5.6.33Connector/Net 6.9.9MySQL for Visual Studio1.2.6

说明:本文结合了很多资料,很难称为原创,但其中也一些关键内容是原创,比如第二次启用迁移之前删除configuration.cs等。

注:MySql 5.7不支持用“来自数据库的Code First”的方式新建ADO.NET实体数据模型,不能进入选择数据对象和设置的步骤,不能选择表,所以选择5.6版。

 

 

2    使用MySql.Data.Entity管理用户和角色

2.1  建立数据库

MySql server中建立数据库sysuser,采用utf8_general_ci字符集。

CREATE SCHEMA `sysuser` DEFAULT CHARACTER SET utf8 ;

2.2      建立项目

vs2015(中文版)中创建一个新的“ASP.NET Web应用程序”项目,选择framework4.5,为项目命名为movieSite,点“下一步”。

在下一个窗口中,选择MVC”,取消“Host in the cloud”,身份验证选“个人用户帐户”,点“确定”。

 

2.3  安装MySql.Data.Entity

在项目中,通过“工具->NuGet包管理器->管理解决方案的NuGet程序包”启动“解决管理方案包”程序,在搜索区域输入“mysql.data.entity”,再单击“浏览”按钮,选择j合适版本(一般选最新版)的“Mysql.Data.Entity”安装。

或,通过“工具->NuGet包管理器->程序包管理控制台”打开程序包管理控制台,在“PM>”提示符后输入“ install-package mysql.data.entity”,回车,直至提示“...已将“MySql.Data.Entityx.x.x”成功安装到...”,说明已安装成功。

安装完成后会在解决方案资源管理器中的引用项下自动生成EntityFrameworkEntityFramework.SqlServerMySql.DataMySql.Data.Entity.EF6等四个引用, 这意味着不必另利安装EntityFramework等程序包了。

2.4  修改Web.config

项目默认数据库连接字符串是指向本机自带的轻量级ms sql数据库的,我们将其修改为指向指定的mysql数据库,并指定utf8字符集,打开项目下的web.config文件,找到的缺省连接字符串,修改并保存如下:

<connectionStrings>

    <add name="DefaultConnection" connectionString="server=localhost;User Id=root;password=password Security Info=True;database=sysuser;charset=utf8"

        providerName="MySql.Data.MySqlClient" />

  </connectionStrings>

如此修改后,项目首次运行时才会将存储用户和角色信息的数据表建立在上述指定的mysql数据库中。

2.5  使迁移生效

vs主菜单中依次选“工具”->Nuget包管器”->“在程序包管理控制台”以打开程序包管理控制台,并输入“Enable-Migrations”,使项目的迁移生效。如下:

 

PM> enable-migrations

正在检查上下文的目标是否为现有数据库...

已为项目 movieSite 启用 Code First 迁移。

 

注:斜体字为程序包管理控制器中的输入输出,下同。

这时,可在解决方案资源管理器中看到生成了Migrations文件夹,并在此文件夹内生成了一个Configuration.cs文件。

 

2.6  新增MySqlHistoryContext.cs

在上述migrations 文件夹下,新增名为MySqlHistoryContext.cs类文件, 并使其内容如下:

 

    public class MySqlHistoryContext :HistoryContext {

        public MySqlHistoryContext(DbConnection connection,string defaultSchema) :base(connection, defaultSchema) { }

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {

            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<HistoryRow>().Property(h => h.MigrationId).HasMaxLength(100).IsRequired();

            modelBuilder.Entity<HistoryRow>().Property(h => h.ContextKey).HasMaxLength(200).IsRequired();

        }

    }

需要添加如下引用:

using System.Data.Common;

using System.Data.Entity;

using System.Data.Entity.Migrations.History;

 

 

2.7  修改configuration.cs

migration 文件夹下,打开configuration.cs文件,修改构造函数如下:

 public Configuration()

        {

            AutomaticMigrationsEnabled = false;

 

            SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());

 

            SetHistoryContextFactory("MySql.Data.MySqlClient", (conn, schema) => new MySqlHistoryContext(conn, schema));

        }

 

SetSqlGenerator方法将生成MySql命令,而非SqlServer命令。若不如此修改,则后续的update-database将出错。

 

2.8  创建自定义的数据库初始化器

由于MySql Provider不支持Entity Framework迁移,我们需要创建一个自定义的数据库初始化器,

给项目增加一个名为 MySqlInitializer.cs 的新类文件,并使其内容如下:

 

using System.Data.Entity;

using System.Data.Entity.Infrastructure;

using System.Linq;

using movieSite.Models;

 

namespace movieSite {

    public class MySqlInitializer :IDatabaseInitializer<ApplicationDbContext> {

        public void InitializeDatabase(ApplicationDbContext context) {

            if (!context.Database.Exists()) {

                // if database did not exist before - create it

                context.Database.Create();

            }

            else {

                // query to check if MigrationHistory table is present in the database

                var migrationHistoryTableExists = ((IObjectContextAdapter)context).ObjectContext.ExecuteStoreQuery<int>(

                string.Format(

                  "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '{0}' AND table_name = '__MigrationHistory'",

                  "sysuser"));

 

                // if MigrationHistory table is not there (which is the case first time we run) - create it

                if (migrationHistoryTableExists.FirstOrDefault() == 0) {

                    context.Database.Delete();

                    context.Database.Create();

                }

            }

        }

    }

}

 

注意:sysuser为先前建立的数据库的名称。

特殊注意:sysuser为先前建立的数据库的名称。不同的数据库时要根据实际情况进行变更。

 

2.9  修改IdentityModel.cs文件

在项目的Models文件夹下,修改 IdentityModel.cs文件代码,在 ApplicationDbContext()方法中增加如下语句:

 Database.SetInitializer(new MySqlInitializer());

2.10  修改start.cs文件

Startup.cs文件中,我们可以找到一个配置方法,通过这个方法,我们将调用CreateRolesandUsers()方法来创建缺省的用户角色和用户,我们将检查角色是否已创建,如果角色,如Admin,还没有创建,那么我们将创建一个新的“Admin”角色,再创建一个缺省用户并设置其角色为Admin。我们将使用该用户作为超级用户,该用户可通过MVC应用创建新的角色。

       public void Configuration(IAppBuilder app)

        {

            ConfigureAuth(app);

            createRolesandUsers();

        } 

 

 

 private void createRolesandUsers() {

            ApplicationDbContext context =new ApplicationDbContext();

 

            var roleManager =new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));

            var UserManager =new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));

 

 

            // In Startup iam creating first Admin Role and creating a default Admin User   

            if (!roleManager.RoleExists("Admin")) {

 

                // first we create Admin rool  

                var role =new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();

                role.Name = "Admin";

                roleManager.Create(role);

 

                //Here we create a Admin super user who will maintain the website                 

 

 

                var user =new ApplicationUser();

                user.UserName = "360932808@qq.com";//一定要与下同,否则无法登录。

                user.Email = "360932808@qq.com";

 

                string userPWD ="S1kd6#N_0";

 

                var chkUser = UserManager.Create(user, userPWD);

 

                //Add default User to Role Admin  

                if (chkUser.Succeeded) {

                    var result1 = UserManager.AddToRole(user.Id,"Admin");

 

                }

            }

 

            // creating Creating Manager role   

            if (!roleManager.RoleExists("Manager")) {

                var role =new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();

                role.Name = "Manager";

                roleManager.Create(role);

 

            }

 

            // creating Creating Employee role   

            if (!roleManager.RoleExists("Employee")) {

                var role =new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();

                role.Name = "Employee";

                roleManager.Create(role);

 

            }

        }

 

引入如下空间:

using movieSite.Models;

using Microsoft.AspNet.Identity;

using Microsoft.AspNet.Identity.EntityFramework;

 

2.11  修改HomeController.cs

2.11.1  增加命名空间

using Microsoft.AspNet.Identity;

using Microsoft.AspNet.Identity.EntityFramework;

using movieSite.Models;

 

2.11.2  增加以下方法:

 public string CurrentRole() {

            if (User.Identity.IsAuthenticated) {

                var user = User.Identity;

                ApplicationDbContext context =new ApplicationDbContext();

                var UserManager =new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));

                var s = UserManager.GetRoles(user.GetUserId());

                string re ="";

                for (int i=0;i<s.Count;i++) {

                    re += s[i].ToString()+"_";

                }

                return re;

            }

            return "";

        }

 

2.11.3  修改Index方法

如下,增加ViewBag.Role = CurrentRole();

这样就可以将用户的角色传到页面了。如果一个用户有多角色,则角色字符串为多个角色名的组合,且中间以_”分隔。

  public ActionResult Index() {

            ViewBag.Role = CurrentRole();

            return View();

        }

 

2.12  运行

Ctrl+F5运行项目,可进行用户注册、登录等操作,在数据库中自动生成相关表。如下图:

 

 

注:若出错如下错误,停止调试运行并稍后重试即可

 

 

,若出现其他错误,检查前述各步骤,尤其检查2.8

 

 

3    引入业务数据管理

来自数据库的Code First”非常有用,既可发挥Code First的优势,也充分利用原有的数据库设计,当要对一个已有的数据库进行开发时,这种技术是最好的选择。为了完成演练,先在数据库端,建立如下数据库和表:

CREATE SCHEMA `moviesdb` DEFAULT CHARACTER SET utf8 ;

创建一个表。

CREATE TABLE `moviesdb`.`movies` (

  `id` INT NOT NULL AUTO_INCREMENT,

  `title` NVARCHAR(50) NULL,

  `releasedate` DATE NULL,

  `genre` NVARCHAR(20) NULL,

  `price` DECIMAL NULL,

  PRIMARY KEY (`id`));

 

3.1  添加数据实体对象

在解决方案资源管理器右击Models文件夹,依次选“添加”、“新建项”、“数据”、“ADO.NET实体数据模型”,命名模型的名称,选“来自数据库的Code First”,如下列各图:

 

注意:名称为Model+库名(非必须)。

 

 

 

 

 完成后生成下图所示的上下文类文件和实体类:

 

 

 

 

 

 

3.2  修改web.config文件

在新生成的连接字符串的connectionString项中增加charset=utf8项。

3.3  修改实体文件

修改Models文件夹下的movies.cs

 public int id {get;set; }

 

        [StringLength(50)]

        [Display(Name ="影片名称")]

        public string title {get;set; }

 

        [Column(TypeName ="date")]

        [Display(Name ="发行日期")]

        public DateTime? releasedate {get;set; }

 

        [StringLength(20)]

        [Display(Name ="流派")]

        public string genre {get;set; }

        [Display(Name ="价格")]

        public decimal? price {get;set; }

通过“文件->高级保存选项”,将此文件的编码格式设为“Unicode (UFT-8带签名)-代码页65001”。

3.4  删除Configuration.cs

Migrations文件夹下删除Configuration.cs文件,因为该文件是上次执行enable-migrations命令时生成的,指向的上下文为当时唯一的ApplicationDbContext,现在要对名为ModelMoviesDb的上下文对应的数据库进行迁移,就要先删除原来的Configuration.cs文件,否则,后述的迁移就会失效。

3.5  启用迁移

ModelMoviedb启用迁移

 

PM> enable-migrations -ContextTypeName ModelMoviesDb

已为项目 movieSite 启用 Code First迁移。

PM>

此时,在Migrations文件夹下生成了新的Configuration.cs文件,该文件指向的上下文为ModelMoviesDb,如下(见粗体):

...

   internal sealed class Configuration : DbMigrationsConfiguration<movieSite.Models.ModelMoviesDb>

...

3.6  修改Configuration.cs

同前,增加SetSqlGeneratorSetHistoryContextFactory方法,修改后如下:

...

 public Configuration()

        {

            AutomaticMigrationsEnabled = false;

 

            SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());

 

            SetHistoryContextFactory("MySql.Data.MySqlClient", (conn, schema) => new MySqlHistoryContext(conn, schema));

        }

...

 

 

3.7  创建空迁移

 

PM> add-migration InitialCreate  -IgnoreChanges

正在为迁移“InitialCreate”搭建基架。

此迁移文件的设计器代码包含当前 Code First 模型的快照。在下一次搭建迁移基架时,将使用此快照计算对模型的更改。如果对要包含在此迁移中的模型进行其他更改,则您可通过再次运行“Add-Migration InitialCreate”重新搭建基架。

PM>

 

3.8  应用迁移

PM> update-database

指定“-Verbose”标志以查看应用于目标数据库的 SQL 语句。

正在应用显式迁移: [201611090355087_InitialCreate]。

正在应用显式迁移: 201611090355087_InitialCreate。

正在运行 Seed 方法。

PM>

 

 

3.9  修改models中的movies

增加如下内容:

  [StringLength(200)]

        [Required]

        [Display(Name ="链接地址")]

        public string Url {get;set; }

3.10  修改ModelMoviedb

增加

  modelBuilder.Entity<movies>()

               .Property(e => e.Url)

               .IsUnicode(false);

3.11  增加迁移

 

PM> add-migration movieaddurl

正在为迁移“movieaddurl”搭建基架。

此迁移文件的设计器代码包含当前 Code First 模型的快照。在下一次搭建迁移基架时,将使用此快照计算对模型的更改。如果对要包含在此迁移中的模型进行其他更改,则您可通过再次运行“Add-Migration movieaddurl”重新搭建基架。

PM>

 

此时,在Migrations文件夹中生成201611090358552_movieaddurl.cs文件,内容如下:

namespace movieSite.Migrations

{

    using System;

    using System.Data.Entity.Migrations;

    

    public partial class movieaddurl :DbMigration

    {

        public override void Up()

        {

            AddColumn("moviesdb.movies","Url", c => c.String(nullable:false, maxLength: 200, unicode:false));

        }

        

        public override void Down()

        {

            DropColumn("moviesdb.movies","Url");

        }

    }

}

3.12  修改迁移文件

打开上述的201611090358552_movieaddurl.cs文件,删除其中的“moviesdb.”字符中,并在up方法内增加Sql语句。修改后如下:

...

 AddColumn("movies", "Url", c => c.String(nullable: false, maxLength: 200, unicode: false));

 Sql("UPDATE movies  SET  url =''");

...

DropColumn("movies", "Url");

...

如不修改,则在实施迁移时会出现Table 'moviesdb.moviesdb.movies' doesn't exist”的错误提示,且迁移失败。

3.13  实施迁移

PM> update-database

指定“-Verbose”标志以查看应用于目标数据库的 SQL 语句。

正在应用显式迁移: [201611090358552_movieaddurl]。

正在应用显式迁移: 201611090358552_movieaddurl。

正在运行 Seed 方法。

PM> 

 

结果,数据库修改成功。

 

 

3.14  生成控制器

先生成一下项目,再添加控制器:

 

3.15  使用CRUD页面(略)

0 0