目前.Net主流的ORM有SqlSugar、Entity Framework、Dapper,其它的我就不列舉了。其實和Java那邊ibatis相比,他們都比較輕量。之前用ibatis開發,真的很麻煩,而且在XML裡面配置總感覺不太友好。
首先DbFirst模式,先在資料庫建好表結構,然後在專案中生成實體。
引入包:Microsoft.EntityFrameworkCore.Tools、Microsoft.EntityFrameworkCore.Design、Pomelo.EntityFrameworkCore.MySql
寫一個類繼承於DbContext
public class MyContext : DbContext { public MyContext(DbContextOptions<MyContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); } }
在ConfigureServices方法中寫入下面這句程式碼
services.AddDbContext<MyContext>(options => options.UseMySql(Configuration.GetConnectionString("dbconn")));
在程式包管理控制檯中輸入命令:
Scaffold-DbContext "server=localhost;user id=root;password=zhang.1122;port=3306;database=MicroservicesCoreDB;Charset=utf8;SslMode=None" "Pomelo.EntityFrameworkCore.MySql" -OutputDir Models -Context MyContext -UseDatabaseNames
-OutputDir Models表示生成的實體類放在Models資料夾下
-Context MyContext表示生成的資料庫上下文物件的名稱
-UseDatabaseNames表示完全按照資料的欄位名和表名來生成實體物件,如果不加這個,預設會帕斯卡命名
後續如果新加了表,執行下面這個命令:
Scaffold-DbContext -Force "Server=localhost;port=3306;database=MicroservicesCoreDB;uid=root;pwd=zhang.1122;CharSet=utf8" -Provider "Pomelo.EntityFrameworkCore.MySql" -OutputDir Models -Tables report -UseDatabaseNames
-Tables report表示指定要生成的表,如果有多個表可用逗號分隔
按照上面那條命令,每次都會生成一個DbContext物件,預設命名為資料庫名+Context.每次都要刪除重新生成的上下文物件很麻煩,所以有更便捷的命令
Scaffold-DbContext "Server=localhost;port=3306;database=MicroservicesCoreDB;uid=root;pwd=zhang.1122;CharSet=utf8" -Provider "Pomelo.EntityFrameworkCore.MySql" -OutputDir Models -Context MyContext -UseDatabaseNames -Force
-Force命令可以同步資料庫表結構,但是資料庫刪除了一個表,專案中對應的實體類還會存在,需要手動刪除.
在執行命令之前,先重新生成一下專案,如果有報錯的話,會生成不成功的.
第二種是CodeFirst模式
新建一個類DbInitialize,用於生成資料庫及種子資料
public class DbInitialize { /// <summary> /// 建構函式 /// </summary> /// <param name="dbcontext"></param> /// <param name="isDbInitialize"></param> public static void Initlialize(MyContext dbcontext, bool isDbInitialize) { if (isDbInitialize) { dbcontext.Database.EnsureDeleted();//刪除 dbcontext.Database.EnsureCreated();//再建立 dbcontext.Department.Add(new Department { department_name= "開發部", department_num= "2020001", dt= DateTime.Now, remarks = "暫無",
}); dbcontext.SaveChanges();//持久化 } } }
新建一個AppSettings類
public class AppSettings { public bool IsDbInitialize { get; set; } }
在appsettings.json中新增節點
"AppSettings": { "IsDbInitialize": false//是否開啟資料庫建立 }
在ConfigureServices註冊
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<MyContext>(options => options.UseMySql(Configuration.GetConnectionString("dbconn"))); services.AddMvc(options => { options.Filters.Add(typeof(GlobalExceptionFilter)); });
services.AddOptions();
services.Configure<AppSettings>(Configuration.GetSection("AppSettings")); }
修改Configure方法
public void Configure(IApplicationBuilder app, IHostingEnvironment env, MyContext context, IOptions<AppSettings> appSettings) { app.UseAuthentication(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } DbInitialize.Initlialize(context, appSettings.Value.IsDbInitialize); //開啟資料庫指令碼建立,謹慎!!! app.UseMvc(); }
這種每次都要刪庫?,資料庫連線字串一定要檢查好,以免誤刪別的庫.
還有另外一種方法
修改Configure方法,加入以下程式碼
using (var scope = app.ApplicationServices.CreateScope()) { var context= scope.ServiceProvider.GetService<MyContext>(); context.Database.EnsureCreated();//沒有則自動建立資料庫 }
第一次資料庫沒建立的時候,會自動建立資料庫
後續如果新增或修改了實體,先執行add-migrate createxxxTable命令,在執行Update-Database createxxxTable即可,會自動生成一個遷移表,記錄每一次的遷移。
我們也可以將EnsureCreated()改為Migrate(),這樣每次只需執行add-migrate createxxxTable命令即可,無需執行Update-Database createxxxTable命令.
using (var scope = app.ApplicationServices.CreateScope()) { var context = scope.ServiceProvider.GetService<DBContext>(); context.Database.Migrate() ;//執行遷移 }
對了,我們可以在DBContext類的OnModelCreating方法中註冊實體與資料庫的對映關係,會根據對映關係生成對應的資料庫表結構.
protected override void OnModelCreating(ModelBuilder modelBuilder) { #region modelBuilder.ApplyConfiguration(new DepartmentEntityTypeConfiguration()); #endregion base.OnModelCreating(modelBuilder); }
class DepartmentEntityTypeConfiguration : IEntityTypeConfiguration<Department> { public void Configure(EntityTypeBuilder<Department> builder) { //定義主鍵 builder.HasKey(p => p.Id); builder.ToTable("department"); builder.Property(p => p.department_name).HasMaxLength(20); builder.Property(p => p.department_num).HasMaxLength(30); builder.Property(p => p.remarks).HasMaxLength(30); builder.Property(p => p.dt); } }
如有不足,望見諒!?