目錄
?文章來源地址http://www.zghlxwxcb.cn/news/detail-764152.html
一、EF Core概述
1.1 什么是ORM??
1.2 EF Core的性能怎么樣?
二、EF Core入門
2.1 什么是Migration數(shù)據(jù)庫遷移:
2.2? EF Core數(shù)據(jù)的增刪改查
2.2.1 增加數(shù)據(jù)
2.2.2 查詢數(shù)據(jù)
?2.2.3 修改和刪除數(shù)據(jù)
三、EF Core的實體類配置
3.1 約定大于配置
3.2 EF Core兩種配置方式
3.2.1 Data Annotation
3.2.2? Fluent API?
3.2.3 兩種方式的比較
3.3 Fluent API 的基本使用
?3.4 EF Core主鍵類型的選擇
?3.4.1 普通自增
3.4.2 Guid算法
?四、關(guān)系配置
4.1 一對多
4.2 關(guān)聯(lián)數(shù)據(jù)的獲取
4.3 實體類對象的關(guān)聯(lián)追蹤
?
一、EF Core概述
Entity Framework Core(簡稱EF Core) 是.NET Core中的ORM (object relational mapping,對象關(guān)系映射) 框架。它可以讓開發(fā)者面向?qū)ο蟮姆绞竭M行數(shù)據(jù)庫操作。
1.1 什么是ORM??
對象:c#中的對象
關(guān)系:關(guān)系數(shù)據(jù)庫
映射:關(guān)系數(shù)據(jù)庫和c#對象之間搭建的一座橋梁
? ? ? ? 我們知道在.NET中可以用過ADO.NET連接數(shù)據(jù)庫然后執(zhí)行SQL語句來操作數(shù)據(jù)庫中的數(shù)據(jù)。而ORM可以直接通過操作c#對象的方式操作數(shù)據(jù)庫。
如下通過創(chuàng)建c#對象的方式把數(shù)據(jù)插入數(shù)據(jù)庫,省去編寫Insert語句:
User user = new User(){Name="li",Password="123456"};
orm.Save(user);
注意:ORM只是對ADO.NET的封裝,ORM底層任然是通過ADO.NET來訪問數(shù)據(jù)庫
?
1.2 EF Core的性能怎么樣?
? ? ? ? EF Core是把對c#對象的操作轉(zhuǎn)換成SQL語句,由于SQL語句是自動生成的,所以如果使用不當(dāng)就會產(chǎn)生低性能的數(shù)據(jù)庫操作。
?
二、EF Core入門
EF Core用于將對象和數(shù)據(jù)庫中的表進行映射,因此需要創(chuàng)建實體類和數(shù)據(jù)庫表兩項內(nèi)容。
例如:使用EF Core通過在數(shù)據(jù)庫中保存書的信息.
?1、創(chuàng)建Book實體類
?2、為項目安裝NuGet包Microsoft.EntityFrameworkCore.SqlServer?
?3、創(chuàng)建一個實現(xiàn)了IEntityTypeConfiguration泛型接口的實體類的配置類BookEntityConfig,它用于配置實體類和數(shù)據(jù)庫的對應(yīng)關(guān)系。
?????????很容易發(fā)現(xiàn),這里對實體類進行配置的時候沒有配置各個屬性在數(shù)據(jù)庫中的列名和數(shù)據(jù)類型,EF Core將會默認把屬性的名字作為列.名,并且根據(jù)屬性的類型來推斷數(shù)據(jù)庫表名各列的數(shù)據(jù)類型。
?4、創(chuàng)建一個繼承自DbContext 的TestDbContext類。
?
2.1 什么是Migration數(shù)據(jù)庫遷移:
面向?qū)ο蟮腛RM開發(fā)中,數(shù)據(jù)庫不是程序員手動創(chuàng)建的,而是根據(jù)對象的定義變化,自動更新數(shù)據(jù)庫中的表以及表結(jié)構(gòu)的操作,叫作Migration(遷移)。
搭建Migration步驟:
- 使用NuGet安裝Microsoft.EntityFrameworkCore.Tools。
- 在“程序包管理控制臺”執(zhí)行數(shù)據(jù)庫遷移指令“Add-Migration InitialCreate”。(InitialCreate:當(dāng)前的migration的名字)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Add-migration作用:根據(jù)實體類及配置生成操作數(shù)據(jù)庫的遷移代碼
執(zhí)行成功后多出了一個migration文件夾
- 在“程序包管理控制臺”執(zhí)行Update-Database,這樣創(chuàng)建數(shù)據(jù)庫的相關(guān)代碼才會被執(zhí)行,數(shù)據(jù)表才會生成。
? ? ? ?注意:如果在使用該指令時,顯示“證書鏈?zhǔn)怯刹皇苄湃蔚念C發(fā)機構(gòu)頒發(fā)的”,主需要在數(shù)據(jù)庫配置處添加TrustServerCertificate=true即可,具體可看我的博文介紹:https://mp.csdn.net/mp_blog/creation/editor/132865793https://mp.csdn.net/mp_blog/creation/editor/132865793執(zhí)行成功后我們發(fā)現(xiàn)此時數(shù)據(jù)庫中已經(jīng)生成了我們創(chuàng)建的T-Books表格:
????????當(dāng)我們要修改數(shù)據(jù)庫內(nèi)容時 ,只需要修改相關(guān)實體類的內(nèi)容,再次執(zhí)行遷移指令A(yù)dd-migration InitialCreate以及更新指令Update-Database即可,但是此時遷移指令的命名因為采用不同的名字。
?
2.2? EF Core數(shù)據(jù)的增刪改查
? ? ? ? 如上述代碼我們知道,Books屬性對應(yīng)數(shù)據(jù)庫中的T_Books表,Books屬性是DbSet<Book>類型的。因此只需要操作Books屬性就可以向數(shù)據(jù)庫中添加數(shù)據(jù)。但是通過c#代碼修改Books屬性種的數(shù)據(jù)只是修改了內(nèi)存的數(shù)據(jù),還需要調(diào)用異步方法SaveChangesAsync把修改的內(nèi)容保存到數(shù)據(jù)庫。
2.2.1 增加數(shù)據(jù)
????????此時刷新數(shù)據(jù)庫,發(fā)現(xiàn)數(shù)據(jù)已經(jīng)成功寫入 。這樣我們就成功實現(xiàn)不用編寫SQL語句,而是通過創(chuàng)建對象和對象賦值的方法完成對數(shù)據(jù)庫的操作。
2.2.2 查詢數(shù)據(jù)
????????Books屬性對應(yīng)數(shù)據(jù)庫中的T_Books表,Books屬性是DbSet<Book>類型的,而DbSet實現(xiàn)了IEnumerable<T>接口,因此可以使用LINQ操作對DbSet進行數(shù)據(jù)查詢。EF Core會把LINQ操作轉(zhuǎn)換為SQL語句。
?例如查詢所有書籍以及使用條件查詢:
using TestDbContext ctx = new TestDbContext();
Console.WriteLine("***所有書籍***");
foreach (Book b in ctx.Books)
{
Console.WriteLine($"Id={b.Id},Title={b.Title},Price={b.Price}");
}
Console.WriteLine("***所有價格高于80元的書籍***");
IEnumerable<Book> books2 = ctx.Books.Where(b => b.Price > 80);
foreach (Book b in books2)
{
Console.WriteLine($"Id={b.Id},Title={b.Title},Price={b.Price}");
}
? ? ? ? 也可以使用LINQ進行復(fù)雜的數(shù)據(jù)查詢,例如Single,F(xiàn)irstOrDefault,OrderBy等,在這里不就演示了,感興趣的可以自己去嘗試喲。
????????如果對LINQ語法模糊的歡迎跳轉(zhuǎn)到我的LINQ博文:https://mp.csdn.net/mp_blog/creation/editor/132326038https://mp.csdn.net/mp_blog/creation/editor/132326038
?2.2.3 修改和刪除數(shù)據(jù)
? ? ? ? 使用EF Core對已有數(shù)據(jù)進行修改,我們需要先把修改的數(shù)據(jù)查詢出來,然后進行修改,再執(zhí)行SaveChangesAsync保存修改即可。
修改數(shù)據(jù)庫內(nèi)容語法:
using TestDbContext ctx = new TestDbContext();
var b = ctx.Books.Single(b => b.Title == ".net");
b.AuthorName = "li";
await ctx.SaveChangesAsync();
刪除數(shù)據(jù)庫某條數(shù)據(jù)語法:
using TestDbContext ctx = new TestDbContext();
var b = ctx.Books.Single(b => b.Title == ".net");
ctx.Books.Remove(b);
await ctx.SaveChangesAsync();
????????注意:我們不論是修改還是刪除數(shù)據(jù),都要先執(zhí)行數(shù)據(jù)的查詢操作,把數(shù)據(jù)查詢出來,在執(zhí)行相應(yīng)操作。這樣EF Core的底層其實發(fā)生了先執(zhí)行Select的SQL語句,再執(zhí)行Update或者delete語句。
?
三、EF Core的實體類配置
3.1 約定大于配置
EF Core采用“約定大于配置”的設(shè)計原則,默認按照約定根據(jù)實體類以及DbContext的定義來實現(xiàn)和數(shù)據(jù)庫表的映射配置,除非用戶顯示指定了配置規(guī)則。
主要規(guī)則總結(jié):
- 數(shù)據(jù)庫表名采用上下文類中對應(yīng)的DbSet的屬性名;
- 數(shù)據(jù)庫表列的名采用實體類屬性的名字,數(shù)據(jù)類型采用跟實體類兼容的數(shù)據(jù)類型;
- 數(shù)據(jù)庫表列的可空取決于對應(yīng)實體類屬性的可空性;
- 名字為Id的屬性為主鍵,如果主鍵為short,int或者long類型,主鍵默認采用自動增長;
3.2 EF Core兩種配置方式
3.2.1 Data Annotation
????????Data Annotation(數(shù)據(jù)注釋)指通過.NET提供的Attribute對實體類,屬性等進行標(biāo)注的方式來實現(xiàn)實體類配置。
?基本使用方法:
[Table("T_Books")] //將實體類對應(yīng)的表名配置為 T_Books
public class Book
{
public long Id { get; set; } //這是主鍵(EF Core默認約束規(guī)定)
[MaxLength(50)] //設(shè)置最大長度
[Required] //設(shè)置為不為空
public string Title { get; set; }
public DateTime PubTime { get; set; }
public double Price { get; set; }
[MaxLength(20)]
[Required]
public string AuthorName { get; set; }
}
3.2.2? Fluent API?
? ? ? ? 就是前面講解的BookEntityConfig模板,采用builder.ToTable("表名")的方法
3.2.3 兩種方式的比較
? ? ? ? 看起來很容易發(fā)現(xiàn)使用Data Annotation方法更簡單,只需要在實體上加入Attribute即可,不用像Fluent API一樣寫單獨的配置類,但是Fluent API是官方推薦的用法,原因如下:
(1)Fluent API能夠更好的進行職責(zé)劃分,所有和數(shù)據(jù)庫相關(guān)的內(nèi)容都放在配置類中。
(2)Fluent API和Data Annotation可以同時使用,但是Fluent API優(yōu)先級高于Data Annotation
?
3.3 Fluent API 的基本使用
(1)排除屬性映射:默認情況下,一個實體類的全部屬性都會映射到數(shù)據(jù)庫表中,但是使用ignore配置可以讓EF Core忽略一個屬性。
ModelBuilder.Entity<Blog>().Ignore(b => b.name);
例:
(2)數(shù)據(jù)庫表列名:數(shù)據(jù)庫表中列名默認和屬性名一樣,我們可以使用HasColumnName方法配置一個不同的列名。
ModelBuilder.Entity<Blog>().Property(b => b.Id).HasColumnName(b_Id);
(3)列數(shù)據(jù)類型: EF Core會根據(jù)實體類類型,最大長度等確定字符的數(shù)據(jù)類型。我們可以使用HasColumnType為列指定數(shù)據(jù)類型。
builder.Property(b => b.Id).HasColumnType("varchar(5)");
(4)主鍵:EF Core會默認把名字為Id或者“實體類型+Id”的屬性作為主鍵,我們可以使用HasKey配置其他屬性為主鍵。
ModelBuilder.Entity<Blog>().HasKey(b => b.name);
(5)索引:?EF Core中可以使用HasIndex方法配置索引
?
????????Fluent API還可以使用鏈?zhǔn)秸{(diào)用方法,但是在調(diào)用的時候需要返回值類型相同的才可以使用鏈?zhǔn)秸{(diào)用。VS已經(jīng)提供了非常完善的代碼提示機制,很容易就能知道某個方法能否使用鏈?zhǔn)秸{(diào)用。
?
?3.4 EF Core主鍵類型的選擇
在數(shù)據(jù)庫設(shè)計中,對于主鍵的類型,有自動增長的long類型和Guid類型兩種常用方案。
?3.4.1 普通自增
? ? ? ? 優(yōu)點:自增long類型的使用非常簡單,所有主流數(shù)據(jù)庫都內(nèi)置了對自增列的支持。新插入的數(shù)據(jù)都會由數(shù)據(jù)庫自動賦值一個新增的、不重復(fù)的主鍵。而且占用磁盤空間小,可讀性強。
? ? ? ? 缺點:自增long類型的主鍵在數(shù)據(jù)庫遷移以及分布式系統(tǒng)(如分庫分表,數(shù)據(jù)庫集群)中使用非常麻煩,而且在高并發(fā)插入的時候性能比較差。
由于自增列的值一般是由數(shù)據(jù)庫自動生成的,因此無法提前獲得新增數(shù)據(jù)行的主鍵值,我們需要把數(shù)據(jù)保存到數(shù)據(jù)庫后才能獲得主鍵值:
3.4.2 Guid算法
Guid算法使用網(wǎng)卡的MAC(medium access control,介質(zhì)訪問控制)地址、時間戳等信息生成一個全球唯一的ID。
? ? ? ? 優(yōu)點:簡單,高并發(fā),全局唯一
? ? ? ? 缺點:磁盤占用空間大
注意:由于Guid算法生成的值是不連續(xù)的,因此不能把Guid類型的主鍵設(shè)置為聚集索引,因為聚集索引是按順序保存主鍵的,在插入Guid類型主鍵的時候,它將導(dǎo)致新插入的每天數(shù)據(jù)都要經(jīng)歷查找合適位置的過程,當(dāng)數(shù)據(jù)量特別大的時候性能就很特別糟糕。
????????在SQLServer中,可以設(shè)置主鍵為非聚集索引,但在MySQL中,如果我們使用InnoDB引擎,那么主鍵是強制聚集索引的,因此在SQL Server中我們使用Guid(也就是uniqueidentifier類型)作為主鍵一定不能把主鍵設(shè)置為聚集索引。
?
接下來演示一下Guid類型主鍵的用法:
? ? ? ? (1)創(chuàng)建一個實體類Author:
? ? ? ? (2)在TestDbContext類中增加一個DbSet屬性(TestDbContext類像一個數(shù)據(jù)庫,管理著多個DbSet。一般項目每增加一個實體類,都在對應(yīng)的TestDbContext類中添加對應(yīng)的DbSet屬性):
? ? ? ? ?(3)執(zhí)行Add-Migration和Update-database生成相關(guān)數(shù)據(jù)表:
? ? ? ? (4)?插入數(shù)據(jù)到數(shù)據(jù)庫表中:
執(zhí)行后:
?
?四、關(guān)系配置
4.1 一對多
舉例講解:比如文章與評論就是一對多關(guān)系,一篇文章對應(yīng)多條評論
????????定義實體類:
class Article
{
public long Id { get; set; } //主鍵
public string Title { get; set; }
public string Content { get; set; }
public List<Comment> Comments { get; set; } = new List<Comment>(); //此文章的多條評論
}
class Comment
{
public long Id { get; set; } //主鍵
public Article Article { get; set; } //評論屬于那篇文章
public string Message { get; set; }
}
? ? ? ? 實體類配置(對于一對多的配置主要是倒數(shù)第四橫排,語法是HasXXX....withXXX,其中XXX表示One or Many):
class ArticleConfig : IEntityTypeConfiguration<Article>
{
public void Configure(EntityTypeBuilder<Article> builder)
{
builder.ToTable("T_Articles");
builder.Property(a => a.Content).IsRequired().IsUnicode(true);
builder.Property(a =>a.Title).IsRequired().IsUnicode(true).HasMaxLength(255);
}
}
class CommentConfig : IEntityTypeConfiguration<Comment>
{
public void Configure(EntityTypeBuilder<Comment> builder)
{
builder.ToTable("T_Comments");
builder.HasOne<Article>(c =>c.Article).WithMany(a => a.Comments).IsRequired();
builder.Property(c =>c.Message).IsRequired().IsUnicode();
}
}
? ? ? ? ?插入數(shù)據(jù):
?
4.2 關(guān)聯(lián)數(shù)據(jù)的獲取
? ? ? ? 例如 把Id==1的文章以及評論輸出:
?
4.3 實體類對象的關(guān)聯(lián)追蹤
? ? ? ? 我們可以不給Comments屬性添加對象,而是給Comment對象的Article屬性賦值的方式完成數(shù)據(jù)的插入。
Article a = new Article();
a.Title = "EF Core入門學(xué)習(xí)";
a.Content = ".net是一個十分偉大的平臺";
Comment b1 = new Comment() { Message = "支持", Article = a };
Comment b2 = new Comment() { Message = "太酷啦", Article = a };
using TestDbContext ctx = new TestDbContext();
ctx.Comments.Add(b1)
ctx.Comments.Add(b2)
?
?
后續(xù)的一對多以及多對多就不展開講解了,基本方法都差不多,后續(xù)時間充分的話再進行補充文章來源:http://www.zghlxwxcb.cn/news/detail-764152.html
?
到了這里,關(guān)于【c#,.NET】Entity Framework Core基礎(chǔ)詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!