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. 運行項目


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM