伴随着.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等相关的知识会在另外的篇章中讲解。现附加源码下载地址,以供参考。
备注: 源码使用注意事项
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. 运行项目