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. 运行项目

  • 相关阅读:
    1012 The Best Rank (25 分)(排序)
    1011. World Cup Betting (20)(查找元素)
    1009 Product of Polynomials (25 分)(模拟)
    1008 Elevator (20 分)(数学问题)
    1006 Sign In and Sign Out (25 分)(查找元素)
    1005 Spell It Right (20 分)(字符串处理)
    Kafka Connect 出现ERROR Failed to flush WorkerSourceTask{id=local-file-source-0}, timed out while wait
    flume、kafka、avro组成的消息系统
    Java23种设计模式总结【转载】
    Java编程 思维导图
  • 原文地址:https://www.cnblogs.com/wangjianhui008/p/15776020.html
Copyright © 2011-2022 走看看