zoukankan      html  css  js  c++  java
  • Asp.Net Core MVC + Code First + Mysql 项目创建以及相关配置

    伴随着.net core 技术的成熟,使用.net 开发的项目可以轻松实现跨平台。今天记录一下 Asp.Net Core MVC + Code First + MySql 的用法,开发工具依然是 Visual Studio(此项目用的是Visual Studio 2019).

    1. 创建新项目,选择Asp.Net Core MVC 模板

    2. 填写项目名称和解决方案名称,如下图所示

     解决方案名称与项目名称最好有所区别,因为下面还要在该解决方案下添加别的项目(实体类项目以及数据仓促项目等),填写完成后点击下一步,如下图所示

    3. 创建项目

      点击创建,Visual Studio开始创建项目。如下图所示

    4. 添加实体类项目(CoreMvc.Entity)

      添加类库项目是为了存放数据实体类,用来生成数据库中对应的数据表。 右击解决方案选择 添加->新项目,如下图所示

     在弹出的添加界面中选择类库项目,如下图所示

     点击下一步,输入项目名称(CoreMvc.Entity),如下图所示

     点击下一步,选择合适的目标框架(和CoreMvc.Web项目的框架保持一致),如下图所示

     点击创建,实体类项目创建成功!如下图所示

     

     5. 添加数据仓储项目(CoreMvc.Repository)

      按照步骤4 添加另外一个类库项目,并命名 CoreMvc.Repository(创建此项目的目的是为了存放数据库上下文文件,以及存放项目迁移的纪录),创建好后如下图所示

     6.  CoreMvc.Entity项目下添加实体类

      在 CoreMvc.Enity项目下 添加两个实体类(DepartMent 和 User)以及一个基础类(EntityBase)代码如下

    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace CoreMvc.Entity
    {
        /// <summary>
        /// 数据表基类(所有的表都应该继承该表)
        /// </summary>
        public class EntityBase
        {
            /// <summary>
            /// 编号(每张表都应该有ID,并且自动生成,此处使用Guid作为主键)
            /// </summary>
            [Key]
            public Guid Id { get; set; } = Guid.NewGuid();
    
            /// <summary>
            /// 名称
            /// </summary>
            [Required(ErrorMessage = "名称是必填项")]
            public string Name { get; set; }
    
            /// <summary>
            /// 创建时间(默认当前时间)
            /// </summary>
            public DateTime CreateTime { get; set; } = DateTime.Now;
    
            /// <summary>
            /// 修改时间(默认当前时间)
            /// </summary>
            public DateTime UpdateTime { get; set; } = DateTime.Now;
        }
    }
    namespace CoreMvc.Entity
    {
        /// <summary>
        /// 部门表
        /// </summary>
        public class Department:EntityBase
        {
            /// <summary>
            /// 部门描述信息
            /// </summary>
            public string Desc { get; set; }
            /// <summary>
            /// 部门领导
            /// </summary>
            public string DepartmentLeader { get; set; }
            /// <summary>
            /// 部门领导电话
            /// </summary>
            public string LeaderPhone { get; set; }
        }
    }
    using System;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace CoreMvc.Entity
    {
        /// <summary>
        /// 用户表
        /// </summary>
        public class User:EntityBase
        {
            /// <summary>
            /// 年龄
            /// </summary>
            public int Age { get; set; }
            /// <summary>
            /// 性别
            /// </summary>
            public int Sex { get; set; }
            /// <summary>
            /// 住址
            /// </summary>
            public string Address { get; set; }
            /// <summary>
            /// 部门编号(此字段是外键,对应Department表中的Id,对应关系由下面的字段产生)
            /// </summary>
            public Guid DepartmentId { get; set; }
            /// <summary>
            /// 所属部门(在生成的数据库中此字段不显示,只显示DepartmentId,其中ForeignKey指向的是上面定义好的DepartmentId字段)
            /// </summary>
            [ForeignKey("DepartmentId")]
            public Department Department { get; set; }
        }
    }

    7. 在 CoreMvc.Repository项目里 添加NuGet包引用

      右击CoreMvc.Repository项目,选择 “管理NuGet程序包”如下图所示

     在打开的界面中点击“浏览”选项卡,搜索  Microsoft.EntityFrameworkCore,如下图所示

      

    由于创建项目时目标框架选择的是 .Net 5.0,而最新包所依赖的框架是.Net 6.0 因此要降低该包的版本,否则会安装失败,更改包的版本后进行安装,如下图所示

     点击安装,则会安装成功。以同样的步骤 安装 Pomelo.EntityFrameworkCore.MySql 和 Microsoft.EntityFrameworkCore.Relational两个NuGet包

    如果出现下图所示,则表示所依赖的NuGet包已经安装成功

     此处简单说明一下三个包的作用:

      1. Microsoft.EntityFrameworkCore:Entity Framework Core is a lightweight and extensible version of the popular Entity Framework data access technology,提供了数据上下文和DbSet属性,我们在程序里面就是通过数据上下文和DbSet属性来对数据库里面的数据进行操作。

      2. Microsoft.EntityFrameworkCore.Relational:Shared Entity Framework Core components for relational database provider:关系数据库提供者共享EF Core组件。比如我们要将实体映射到数据库中,都是通过这个包完成的。

      3. Pomelo.EntityFrameworkCore.MySql:对于EF Core的Mysql数据库提供者。假如使用的是Mysql数据库,那么就需要安装这个包。对于其他数据库,EF Core提供的有其相对应的提供程序安装包。 

     8. CoreMvc.Repository项目添加CoreMvc.Entity引用

      由于CoreMvc.Repository项目需要用到CoreMvc.Entity项目的实体类,因此在该项目下需要添加 CoreMvc.Entity项目的引用,如图

     在弹出的界面上选择CoreMvc.Entity,如下图所示

     点击确定按钮即可。  

     9. CoreMvc.Repository项目添加数据库上下文

      在CoreMvc.Repository项目里 添加MysqlContext实体类,并继承DbContext,代码如下

      

    using CoreMvc.Entity;
    using Microsoft.EntityFrameworkCore;
    
    namespace CoreMvc.Repository
    {
        /// <summary>
        /// 数据上下文
        /// </summary>
        public class MysqlContext : DbContext
        {
            public MysqlContext(DbContextOptions<MysqlContext> options)
                : base(options)
            {
    
            }
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                base.OnConfiguring(optionsBuilder);
            }
    
            /// <summary>
            /// 部门表(最终生成到数据库的表名可能会转为小写:departments)
            /// </summary>
            public DbSet<Department> Departments { get; set; }
            /// <summary>
            /// 用户号表(最终生成到数据库的表名可能会转为小写:users)
            /// </summary>
            public DbSet<User> Users { get; set; }
            
        }
    }

    10. CoreMvc.Web 项目下 安装Nuget包

      在 CoreMvc.Web项目下需要安装 Microsoft.EntityFrameworkCore.Tools、Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation两个Nuget包,安装步骤参考步骤7,注意对应包的版本的兼容性,安装成功后如下图所示

     简单说明一下各个包的用途:

      1.  Microsoft.EntityFrameworkCore.Tools:Visual Studio中NuGet Package Manager控制台的实体框架核心工具。后续需要需要使用 NuGet Package Manager (程序包管理器控制台)窗口进行数据迁移

      2. Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation:调试时,更改cshtml代码, 刷新浏览器可以更新页面(否则更改了cshtml的代码时,需要重新启动项目,浏览器才可以更新页面)

       需要在Startup.cs 的ConfigureServices方法中添加  services.AddMvc().AddRazorRuntimeCompilation(); 

    11.  CoreMvc.Web 项目下配置数据库连接字符串

      打开appsettings.json文件,添加如下代码

      

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "AllowedHosts": "*",
      "ConnectionStrings": {
        "MyConnectionStr": "Server=localhost;DataBase=CoreMvcTestDB;uid=root;pwd=root123;pooling=true;port=3306;Charset=utf8;sslMode=None;"
      }
    }

    其中 “MyConnectionStr” 是连接字符串的名称(可以随意命名) 

      "Server=localhost" 指连接本地数据库(本地需要安装Mysql数据库,安装方法自行百度解决) 

      “DataBase=CoreMvcTestDB” 指要生成的数据库名称(此处做测试使用,实际开发中应该进行有意义的命名)

      "uid=root" 指本地数据库用户名(安装mysql数据库的时候填写的名字)

      “pwd=root123” 指本地mysql数据库密码(安装mysql数据库的时候设置的密码)

      “pooling=true” 指启用连接池(连接池是一些与数据库有关连接的存放地方,当你需要建立某个连接时,如果它已存在与连接池就不需要新建连接了,速度更快,所以建议还是开启)

      "port=3306;"  指数据库端口(mysql数据库默认端口是 3306)

      “Charset=utf8” 指采用utf8编码 (为了防止存取数据库时中文变乱码或“?”)

      "sslMode=None" 使数据库支持SSL连接

    12. CoreMvc.Web项目添加项目引用

      由于CoreMvc.Web项目需要用到其它两个项目,所以需要在该项目下添加项目引用。因为CoreMvc.Repository项目本身就引用了CoreMvc.Entity,所以CoreMvc.Web项目里只需要添加CoreMvc.Repository引用即可, 具体添加方法参考步骤8,添加完成后结果如下图

    13. 配置相关服务 

      CoreMvc.Web项目下打开Startup.cs文件,添加相关服务配置,最终代码如下

    using CoreMvc.Repository;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    
    namespace CoreMvc.Web
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<MysqlContext>(p => p.UseMySql(Configuration.GetConnectionString("MyConnectionStr"), MySqlServerVersion.LatestSupportedServerVersion));//添加数据库链接
                services.AddMvc().AddRazorRuntimeCompilation(); //调试时,更改cshtml代码, 刷新浏览器可以更新页面内容(需要 引入 Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation 包)
                services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_3_0).AddJsonOptions(opt =>
                {
                    opt.JsonSerializerOptions.PropertyNamingPolicy = null;//匹配大小写(否则实体类中的字段传到View中时全部变成了小写,比如:Department中的DepartmentLeader字段,传到View中时变成了 departmentleader)
                });
                services.AddControllersWithViews();
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
                app.UseHttpsRedirection();
                app.UseStaticFiles();
    
                app.UseRouting();
    
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllerRoute(
                        name: "default",
                        pattern: "{controller=Home}/{action=Index}/{id?}");
                });
            }
        }
    }

     14. 数据迁移

     1. 打开“程序包管理器控制台”

     通过 工具-》Nuget包管理器-》程序包管理器控制台 打开“程序包管理器控制台”窗口

     

     2. 设置启动项目和默认项目

     设置启动项目:因为“包管理器控制台”依赖于包“Microsoft.EntityFrameworkCore.Tools”,此项目中“Microsoft.EntityFrameworkCore.Tools”安装到了CoreMvc.Web项目下(实际开发中也应该安装到此项目下,这样每次迁移数据时就不需要再更换启动项目),所以启动项目应该设置为CoreMvc.Web

    设置默认项目:“包管理器控制台”中的默认项目指数据上下文(DbContext)所在的项目,因为CoreMvc.Repository项目下的MysqlContext继承了DbContext,所以默认项目应该设置为 CoreMvc.Repository。

    设置完后,迁移数据时,“包管理器控制台”通过“默认项目”找到“MysqlContext”,然后通过 CoreMvc.Repository 项目下的包“Microsoft.EntityFrameworkCore.Relational”将实体类映射到数据库中。

    3. 数据迁移命令

      A. 添加迁移命令

      在“包管理器控制台中”输入命令 (命令格式:“Add-Migration 迁移名称”)

    Add-Migration Init

     其中“Add-Migration”是固定格式,表示添加迁移,Init是迁移的名称,可以根据实际需求填写,此处Init的意思是初始化数据,运行完此命令后,在CoreMvc.Repository项目下会有迁移记录文件,如下图所示

     B. 更新数据库命令

       输入“添加迁移”命令后,只是多了迁移记录文件,数据还没有更新到数据库中(首次迁移的时候数据库还没有生成,此时可以通过‘Remove-Migration’命令撤回刚才的迁移记录),如果要将数据更新到数据库中,需要输入以下命令

    Update-Database
    

      输入完此命令后,如果出现下图所示内容,表示数据迁移成功

     此时,通过数据库管理工具(Navicat)查看本地数据库,则发现“CoreMvcTestDB”数据库已经生成,如下图所示

     15. 添加控制器

      为了实现数据的增删改查,我们可以在CoreMvc.Web的Controllers文件夹下添加一个空控制器BaseController,用来存放增删改查的基本代码,其它控制器可以继承这个控制器,这样就可以实现代码的重用了。代码如下

    using CoreMvc.Entity;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Dynamic.Core;
    
    namespace CoreMvc.Web.Controllers
    {
        public class BaseController<D,T> : Controller
            where D: DbContext
            where T: EntityBase
        {
            /// <summary>
            /// 链接对象
            /// </summary>
            private D _context;
            public BaseController(D context)
            {
                _context = context;
            }
    
            [HttpGet]
            public virtual JsonResult GetAll(int limit, int offset, string search, string sort, string order, string includes)
            {
                var dbSet = _context.Set<T>().OrderBy(d => d.CreateTime).AsQueryable();
                #region 查询
                if (!string.IsNullOrEmpty(search))
                {
                    dbSet = dbSet.Where(d => d.Name.Contains(search));
                }
                #endregion
                #region 排序
                if (!string.IsNullOrEmpty(sort))
                {
                    dbSet = dbSet.OrderBy(string.Format("{0} {1},CreateTime asc", sort, order));  // 根据某个字段排序,需要引入包:System.Linq.Dynamic.Core
                }
                #endregion
                #region Includes 是否包含关联表的信息
                if (!string.IsNullOrEmpty(includes))
                {
                    includes.Split(',').ToList().ForEach(i =>
                    {
                        dbSet = dbSet.Include(i);
                    });
                }
                #endregion
                int total = dbSet.Count();
                var rows = dbSet.Skip(offset).Take(limit).AsNoTracking().ToList();//AsNoTracking加上之后,对读取的数据不进行跟踪,UpdateAsync不会报错,不然会报
                return Json(new { total = total, rows = rows });
            }
    
            public virtual IActionResult Get(Guid Id, string includes)
            {
                var dbSet = _context.Set<T>().AsQueryable();
                //自动Includes
                if (includes != null)
                {
                    var sp = includes.Split(',').ToList();
                    sp.ForEach(v =>
                    {
                        dbSet = dbSet.Include(v).AsQueryable();
                    });
                }
    
                return Ok(dbSet.FirstOrDefault<T>(m => m.Id == Id));
            }
    
            /// <summary>
            /// 删除数据
            /// </summary>
            /// <param name="datas"></param>
            /// <returns></returns>
            [HttpPost]
            public virtual IActionResult Delete(List<T> datas)
            {
                try
                {
                    _context.RemoveRange(datas);
                    _context.SaveChanges();
                    return Ok(new { status = "success" });
                }
                catch (Exception)
                {
                    return Ok(new { status = "error" });
                }
            }
    
            /// <summary>
            /// 添加或者修改
            /// </summary>
            /// <param name="t"></param>
            /// <returns></returns>
            [HttpPost]
            public virtual IActionResult Submit([FromForm] T t)
            {
                if (!ModelState.IsValid) //判断验证是否成功
                {
                    string error = "";
                    foreach (var key in ModelState.Keys)
                    {
                        var modelstate = ModelState[key];
                        if (modelstate.Errors.Any())
                        {
                            error = modelstate.Errors.FirstOrDefault().ErrorMessage;
                        }
                    }
                    return Ok(new { status = "error" });
                }
                else
                {
                    try
                    {
    
                        var entity = _context.Set<T>().Find(t.Id); //根据Id查询数据库中是否存在该记录
                        if (entity == null) //不存在则添加
                        {
                            _context.Add(t);
                        }
                        else
                        { //存在则修改
                            foreach (var mi in t.GetType().GetProperties()) //遍历view中传来的所有字段
                            {
                                var des = entity.GetType().GetProperty(mi.Name);
                                if (des != null)//如果数据库中所查询的记录包含此字段,则进行赋值修改
                                {
                                    des.SetValue(entity, mi.GetValue(t));
                                }
                            }
                            _context.Entry<T>(entity).State = EntityState.Modified;//将状态设置为修改状态
                            //_context.Update(t);
                        }
                        _context.SaveChanges(); //保存新增或者修改
                        return Ok(new { status = "success" });
                    }
                    catch (Exception error)
                    {
                        return Ok(new { status = "error" });
                    }
                }
    
            }
        }
    }

    然后我们再创建一个DepartmentController,让他继承BaseController,代码如下

    using CoreMvc.Repository;
    using Microsoft.AspNetCore.Mvc;
    
    namespace CoreMvc.Web.Controllers
    {
        public class DepartmentController : BaseController<MysqlContext,Entity.Department>
        {
            private MysqlContext _context;
            public DepartmentController(MysqlContext context):base(context)
            {
                _context = context;
            }
            public IActionResult Index()
            {
                return View();
            }
        }
    }

    数据基本维护的代码完成后,右击Index添加视图,如下图所示,

     点击添加按钮,视图添加成功,此时就可以添加测试数据了。

    16. 添加测试数据

      该程序数据的显示以及增删改查界面使用的是Bootstrap以及BootstrapTable插件。个人比较喜欢bootstrap3,因为它可以更好地兼容bootstraptable插件,但是由于bootstrap版本的不断升级(目前官方最新版本是5.1.3),所以此处我们采用最新的bootstrap版本。

      为了方便使用Table插件,自己封装了一个table.js。除了这些外还需要toastr.css、toastr.min.js、popup.js等插件,现在不用担心这些,文章最后提供了源码下载(最新版本的bootstrap程序源码和bootstrap3版本的程序源码),大家可以下载参考。

      最终的界面如下图所示

      

          

     至此,最简单的Asp.Net.Core Mvc + Code First + Mysql 项目已经完成。由于本篇章的主要要点是讲解项目的架构,所以有关Bootstrap以及BootStraptable等相关的知识会在另外的篇章中讲解。现附加源码下载地址,以供参考。

     CoreMvc项目源码链接

    CoreMvc项目源码链接(bootstrap3版本)

    备注: 源码使用注意事项

    1. 要求本地安装了 visual studio 2019,框架版本是Net5.0

    2. 要求本地安装了mysql数据库

    3. 下载源码到本地并解压(或者通过git直接下载),用Vs2019打开项目

    4. 设置CoreMvc.Web为启动项目

    5. 修改CoreMvc.Web项目下的appsettings.json文件中数据库用户名和数据库密码(安装mysql时的用户名和密码)

    6. 在visual studio中打开程序包管理器控制台,设置默认项目为 CoreMvc.Repository

    7. “程序包管理器控制台”运行 Add-Migration Init命令

    8. "程序包管理器控制台"运行 Update-Database命令

    9. 运行项目

  • 相关阅读:
    Java多线程
    JVM的结构
    CURL POST 请求
    网页504超时 apache php
    Web服务器超时处理
    apache自带压力测试工具ab详解
    好用的日期组件My97DatePicker
    CI源码阅读
    apache rewrite规则详解
    安装mysqli 扩展
  • 原文地址:https://www.cnblogs.com/wangjianhui008/p/15776020.html
Copyright © 2011-2022 走看看