zoukankan      html  css  js  c++  java
  • MVC5+EF6入门教程——实现动态创建数据库与登录验证

    详细步骤

    • 创建文件夹,规划好项目目录
    • 创建相关实体类 (Data Model)
    • 创建 Database Context
    • 创建Initializer, 使用EF初始化数据库,插入测试数据
    • 实现数据库登录验证
    • 总结

    一,创建文件夹,规划好项目目录

      1.根目录下新建一个 ViewModels文件夹:

        Models文件夹里面存放对应于数据库表的实体;

        View中需要显示的数据和Models中实体模型不一定能对应上, 因此需要专门给View使用的自定义数据模型,

        我们称之为ViewModel , 放在   ViewModels文件夹里面。

      2.根目录下新建一个DAL 文件夹:

        DAL 放置数据访问相关类,如MyDbContext.cs, Initializer.cs

     

    二,创建相关实体类 (Data Model)

      为了更加贴近真实情况,我们针对用户建立三个相关的类。 TbUser, TbRole, TbUserRole

        TbUser Entity

        public class TbUser
        {
            public int Id { get; set; }
            public string UserName { get; set; }
            public string Password { get; set; }
            public string  Email { get; set; }
            public virtual ICollection<TbUserRole> TbUserRoles { get; set; }
        }
    View Code

        TbRole Entity

        public class TbRole
        {
            public int Id { get; set; }
            public string RoleName { get; set; }
            public string RoleDescription { get; set; }
            public virtual ICollection<TbUserRole> TbUserRoles { get; set; }
        }
    View Code

        TbUserRole Entity

    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace TestMVC.Models
    {
        public class TbUserRole
        {
            public int Id { get; set; }
            public int UserId { get; set; }
            public int RoleId { get; set; }
            [ForeignKey("UserId")]
            public virtual TbUser TbUser { get; set; }
            [ForeignKey("RoleId")]
            public virtual TbRole TbRole { get; set; }
        }
    }
    View Code

      对于上面几个类的约定和说明:

    • EF生成数据库时,ID 属性将会成为主键。(约定:EF默认会将ID或classnameID生成主键, MSDN建议保持风格的一致性, 都用ID或classnameID, 我们这里都用ID);
    • EF 生成数据库时 , <navigation property name><primary key property name>这种形式的会成为外键. ( 约定 )

      例如外键 TbUserID = TbUser(navigation property)+ID(TbUser的主键) ;

    • 定义为virtual的几个属性是 navigation 属性(virtual非必须, 只是惯例用法);

      navigation 属性保存着其他的关联entity(entities);

      示例中, TbUser和TbUserRole是一对多的关系, TbRole和TbUserRole也是一对多的关系;

      如果是 "多", 属性类型就必须是List( 这里用的是ICollection);

    三,创建 Database Context

      1.通过NuGet安装Entity Framework

      

      2.创建类 MyDbContext.cs , 让他继承自System.Data.Entity.DbContext, 我们用这个类完成EF的功能:

      主要做下面三件事:

      • 为每个entity set创建一个DbSet

        在EF中,通常情况下一个entity set对应数据库中的一张表,一个entity对应表中的一行。

      • 指定一个连接字符串

        构造函数中的 base("MyDbContext") 。

        默认情况下和类名一样,即MyDbContext我们显式的给他指定出来。

      • 指定单数形式的表名

        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        默认情况下会生成复数形式的表,如TbUsers

        PS: 表名用单复数形式看各自的习惯,没有明确的规定。有的公司表名全用单数,有的公司根据表的意思,有单数也有复数。

      MyDbContext.cs

        public class MyDbContext:DbContext
        {
            public MyDbContext()
                : base("MyDbContext")
            { }
            public IDbSet<TbUser> TbUsers { get; set; }
            public IDbSet<TbRole> TbRoles { get; set; }
            public IDbSet<TbUserRole> TbUserRoles { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                //因为表名称默认为复数形式,这里是移除复数形式,所以为单数形式生成
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            }
        }
    View Code

      3.配合上面第2点,需要web.config中的数据库连接字符串:

      如下图,添加connectionStrings节点。注意要web.config中要加上红字部分(表示连接的是Sql Server数据库),不然会出错。

      <connectionStrings>
          <add name="MyDbContext" connectionString="Data Source=.;

       database=TestMvc;uid=sa;pwd=123456;AttachDBFilename=|DataDirectory|TestMVC.mdf;" providerName="System.Data.SqlClient"/>
       </connectionStrings>

      PS: AttachDBFilename=|DataDirectory|TestMVC.mdf设定了数据库文件的存放位置:在项目根目录的App_Data文件夹下

      

    四,创建Initializer, 使用EF初始化数据库,插入测试数据

      PS:EF可以以多种方式建立数据库,我们暂时采用 第一次运行程序时新建数据库,插入测试数据; model改变(和database不一致)时删除重建数据库,插入测试数据。暂时不用管数据丢失的问题,直接drop and re-create比较方便。等后面单独拿一篇出来讲解生产环境中如何不丢失数据修改数据库。

      1.新建类Initializer.cs来完成这个工作:

       Seed方法用我们之前定义的database context(即MyDbContext) 作为参数,通过这个context将entities添加到database中去;

       从上面代码可以看出, Seed方法对每一个entity的类型;

       创建一个colletion à 添加到适当的 DbSet property à 保存到数据库。

      Initializer.cs

        public class Initializer:DropCreateDatabaseIfModelChanges<MyDbContext>
        {
            protected override void Seed(MyDbContext context)
            {
                var tbUsers = new List<TbUser> { 
                    new TbUser{UserName="张三",Password="zhangsan",Email="zhangsan@163.com"},
                    new TbUser{UserName="李四",Password="lisi",Email="lisi@163.com"}
                };
                tbUsers.ForEach(u => context.TbUsers.Add(u));
    
                var tbRoles = new List<TbRole> { 
                    new TbRole{RoleName="管理员",RoleDescription="管理员具有最高权限来对系统进行管理"},
                    new TbRole{RoleName="一般用户",RoleDescription="一般用户具有一些基本的操作权限"}
                };
                tbRoles.ForEach(r => context.TbRoles.Add(r));
                var tbUserRole = new List<TbUserRole> { 
                    new TbUserRole{UserId=1,RoleId=1},
                    new TbUserRole{UserId=1,RoleId=2},
                    new TbUserRole{UserId=2,RoleId=2}
                };
                tbUserRole.ForEach(ur => context.TbUserRoles.Add(ur));
                context.SaveChanges();
            }
        }
    View Code

      2.修改web.config, 通知EF使用我们刚刚写好的Initializer类,找到entityFramework配置节,添加下图方框处内容:

      

       context 配置节中, type 的值对应 (context class的完整描述,程序集)

      databaseInitializer 配置节中 , type 的值对应 (initializer class 的完整描述,程序集)

      PS: 如果你不想EF使用某个context, 可以在context节点里面添加属性disableDatabaseInitialization="true";

    五,实现数据库登录验证

      现在EF一切就绪了,运行程序,当第一次连接数据库时,EF比较model(AccountContext和entity classes) 和database. 如果两边不一致,程序将会drop and re-create(删除并新建)数据库,因为目前我们还没有连接数据库的操作,所以EF还没发挥作用。在第一次连接数据库时才会生效

      AccountController.cs

        public class AccountController : Controller
        {
            private MyDbContext db = new MyDbContext();
            // GET: Account
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult Login()
            {
                ViewBag.LoginState = "登录前...";
                return View();
            }
            [HttpPost]
            public ActionResult Login(TbUser user)
            {
                var userinfo = db.TbUsers.FirstOrDefault(u => u.Email == user.Email && u.Password == user.Password);
                if (userinfo != null)
                    ViewBag.LoginState = userinfo.UserName+"登录后...";
                else
                    ViewBag.LoginState = user.Email + "用户不存在...";
                return View();
            }
        }
    View Code

      Login.cshtml

    @model TestMVC.Models.TbUser
    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Login</title>
    </head>
    <body>
        <div> 
            @ViewBag.LoginState
            @using(Html.BeginForm("Login","Account",FormMethod.Post)){
                @Html.LabelFor(u=>u.Email)<br />
                @Html.TextBoxFor(u=>u.Email)<br />
                @Html.LabelFor(u => u.Password)<br />
                @Html.PasswordFor(u => u.Password)<br />
                <input type="submit" value="登录" />
            }
        </div>
    </body>
    </html>
    View Code

      然后运行Login.cshtml页面,执行效果下:

      

      

      

    六,总结

    OK,到此为止,我们搭建好了EF框架,进行了数据库的初始化,查询了一条用户信息。

    需要说明的是,现在的登录功能还比较简陋,不是真正的登录功能(例如输入项还缺少验证,密码还没有加盐),只是为了说明EF的用法。

    最后再回顾下本章的重点:掌握使用EF开发的整个过程。

    创建Data Modelà创建Database Context à创建databaseInitializerà配置entityFramework的context配置节

      希望大家能清晰的了解上面整个过程,理解每一个过程的作用。

    源码下载

  • 相关阅读:
    DP:Multiplication Puzzle(POJ 1651)
    Heap:Expedition(POJ 2431)
    velocity.js 动画插件
    ES6 新特性
    ps p图
    php 建站 多域名配置 自定义重定向
    移动端开发 资源分享
    拖拽 初体验
    颜色选择器 rgb 与16进制 颜色转换
    web 常用颜色
  • 原文地址:https://www.cnblogs.com/myindex/p/5467229.html
Copyright © 2011-2022 走看看