十年河東,十年河西。莫欺少年窮
學無止境,精益求精
最近再看Net5相關視頻,看的過程中就想把看到的知識通過博客展示出來,因此就有了這篇博客
之前項目中用的DbFirst ,本篇開啓CodeFirst,按照微軟官方提供的說法,是希望大家都用CodeFirst
1、CodeFirst
1.1、新建控制檯項目並引入如下程序集
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
1.2、編寫實體
實體對應的是數據庫的表
public class Book { public long id { get; set; } [Description("書的名稱")] public string Title { get; set; } public DateTime Pubdate { get; set; } public double Price { get; set; } } public class Person { public long id { get; set; } [Description("姓名")] public string Name { get; set; } public string Age { get; set; } public string Address { get; set; } }
1.3、綁定實體和數據表的關係
public class BookConfig : IEntityTypeConfiguration<Book> { public void Configure(EntityTypeBuilder<Book> builder) { builder.ToTable("T_Books"); } } public class PersonConfig : IEntityTypeConfiguration<Person> { public void Configure(EntityTypeBuilder<Person> builder) { builder.ToTable("T_Persons"); builder.Property("Name").HasMaxLength(50).IsRequired(true).HasComment("我是字段備註:姓名"); } }
意味着Book實體對應的表爲 T_Books
builder.Property 聲明字段的一些規則,例如長度最大爲50【HasMaxLength(50)】、字段爲非空字段【IsRequired(true)】、設定字段備註【HasComment】等
如
// builder.ToView<Book>("視圖名稱"); //綁定視圖的模式 //builder.Ignore(A => A.Pubdate);//Pubdate 字段是實體中的字段,但不會出現在Table中,例如默寫通過計算得出的列或者屬性 //builder.Property("Name").HasColumnName("BookName"); //配置列名 在數據表中會展示爲BookName // builder.Property("Name").HasColumnType("varcahr(200)"); //配置列名的數據類型 改變默認的Varchar(MAX) 及 改變數據庫的 NVVARCHAR(MAX) ,不存中文時用這個 //builder.Property("Name").HasDefaultValue("書"); 默認值 //builder.HasKey(A => A.Title);//修改默認主鍵配置 主鍵爲 Title //builder.HasIndex(A => A.Price);//設置價格列爲索引 // builder.HasIndex(A => new { A.Price, A.Pubdate });//設置複合索引 builder.HasIndex(A => A.Price).IsUnique();//設置唯一索引
除了上述的方法外,我們還可以通過數據註解的方式完成字段最大長度設定、是否能爲Null等設置,例如:
[Table("T_Cats")] public class Cat { //當遇到 Int、long、ShortInt、Guid類型時,根據約定,該字段會被設置爲主鍵 public Guid catId { get; set; } [Required] [MaxLength(50)] public string catName { get; set; } [MaxLength(50)] public string sex { get; set; } }
這種方式雖說簡單,但,還是建議大家使用IEntityTypeConfiguration<>的方式進行綁定
例如有這麼個變態需求,當使用MySQL數據時,希望在數據庫中表名爲M_Cats,當在SQLServer數據庫中是希望表名爲T_Cats,那麼如果你使用數據註解的方式就無法完成這個工作,使用IEntityTypeConfiguration<>的方式則可以在void Configure(EntityTypeBuilder<Person> builder)方法中寫相關的邏輯代碼。
1.4、創建數據庫上下文
public class wechatDbContext : DbContext { public DbSet<Book> Books { get; set; } public DbSet<Person> Persons { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); optionsBuilder.UseSqlServer("Data Source=LAPTOP-84R6S0FB;Initial Catalog=wechat;Integrated Security=True"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //從當前程序集命名空間加載所有的IEntityTypeConfiguration modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly); } }
OnConfiguring 方法初始化數據庫鏈接字符串
OnModelCreating 從當前程序集命名空間加載所有的IEntityTypeConfiguration綁定的實體
1.5、通過程序包控制檯,生成數據庫
Add-Migration initDb -- Update-Database
Add-Migration 的語法爲 Add-Migration + 備註,每次備註不允許一樣
Update_DataBase 生成或更新數據庫
當然,如果在實際編碼中修改字段的長度、字段類型,新增字段、刪除字段等操作後,需要執行 Add-Migration 和 Update-DataBase ,執行後數據庫纔會做出響應的改變。
1.6、簡單測試
由於DbContext 繼承了 IDisposable 、因此在編程時,我們需要使用Using ,這樣做是爲了能夠及時的釋放佔用的資源。
簡單測試如下:
using System; using System.Linq; using System.Threading.Tasks; namespace EfCore { internal class Program { static async Task Main(string[] args) { var tsk_1 = add(); var tsk_2 = update(await tsk_1); var tsk_3 = delete(await tsk_1); await tsk_2; await tsk_3; Console.WriteLine("執行完畢"); Console.Read(); } static async Task<int> add() { using (wechatDbContext context = new wechatDbContext()) { Book bok = new Book(); bok.Title = "鋼鐵是怎麼練成的"; bok.Price = 180; bok.Pubdate = DateTime.Now; context.Books.Add(bok); Book bok2 = new Book(); bok2.Title = "平凡的世界"; bok2.Price = 110; bok2.Pubdate = DateTime.Now; context.Books.Add(bok2); return await context.SaveChangesAsync(); } } static async Task update(int addnum) { using (wechatDbContext context = new wechatDbContext()) { var ef = context.Books.Where(A => A.Title == "平凡的世界").FirstOrDefault(); ef.Price = 122; await context.SaveChangesAsync(); } } static async Task delete(int addNum) { using (wechatDbContext context = new wechatDbContext()) { var ef = context.Books.Where(A => A.Title == "鋼鐵是怎麼練成的").FirstOrDefault(); context.Books.Remove(ef); await context.SaveChangesAsync(); } } } }
@天才臥龍的bolero