C# 數據操作系列 - 8. EF Core的增刪改查

来源:https://www.cnblogs.com/c7jie/archive/2020/05/18/12910627.html
-Advertisement-
Play Games

0.前言 到目前為止,我們看了一下如何聲明EF Core的初步使用,也整體的看了下EF Core的映射關係配置以及導航屬性的配置。 這一篇,我帶大家分享一下,我在工作中需要的EF Core的用法。 1. 初始化 在實際開發中,一般都是先設計好數據表再進行開發,所以很少用到EF Core的數據遷移功能 ...


0.前言

到目前為止,我們看了一下如何聲明EF Core的初步使用,也整體的看了下EF Core的映射關係配置以及導航屬性的配置。

這一篇,我帶大家分享一下,我在工作中需要的EF Core的用法。

1. 初始化

在實際開發中,一般都是先設計好數據表再進行開發,所以很少用到EF Core的數據遷移功能。所以EF Core的初始化,一般也指的是EF Core上下文初始化。

1.1 連接字元串

我們通過前面的文章知道,EF Core在上下文初始化的時候,都需要一個鏈接字元串。如果在不考慮後續變更或者上下文的復用性,可以直接在自定義Context里重寫OnConfiguring方法中定義。

如果需要後續變更,那麼就需要在創建自定義EF Core 上下文類的時候,為之添加一個連接字元串的屬性或者欄位,以方便初始化的時候指定。實例:

public class DefaultContext : DbContext
{
    private string Connection { get; set; } = "Data Source=./blogging1.db";
    public DefaultContext(string connection)
    {
        Connection = connection;
    }
    protected override void OnConfiguring(DbContextOptionsBuilder options)
        => options.UseSqlite(Connection);
}

這樣一來,我們在後續使用的時候,就可以指定連接字元串了。當然了,如果有小伙伴有更好的方法也可以分享出來呀。

1.2 配置文件的載入或者實體對象的托管

如果我們不使用配置文件的話,就必須在EF Core的上下文類里添加一個類型是DbSet<T>的屬性。繼續延續上面的實例:

public class SingleModel
{
    public int Id { get; set; }
    public int TargetId { get; set; }
    public SingleTargetModel SingleTarget { get; set; }
}

public class SingleTargetModel
{
    public int Id { get; set; }
    public SingleModel Single { get; set; }
}
public class DefaultContext : DbContext
{
    // 其餘代碼參見 1.1  DefaultContext
    public DbSet<SingleModel> Singles { get; set; }
    public DbSet<SingleTargetModel> Targets { get; set; }
}

以上也就是這一小節標題中的實體對象的托管。我沒找到EF Core官方文檔中對於這種方式的稱呼,所以我就悄悄的搶註了一下為托管。

如果我們使用Config類(也就是 《C# 數據操作系列 - 7. EF Core 導航屬性配置》中介紹的配置類)的話,需要在EF Core中應用配置,具體是:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfiguration(new SingleModelConfig());
    modelBuilder.ApplyConfiguration(new SingleTargeModelConfig());
}

在使用的時候,可以直接:

var context = new DefaultContext("Data Source=demo.db");
var t1 = context.Set<SingleTargetModel>().First();

即使用DbContext.Set<T>,可以獲取到一個數據載入集,當然也可以結合實體類的托管來一起使用。

那麼為什麼,我推薦使用配置類載入嗎?

因為在實際開發中,一個完整的程式或者網站實體類都會大於10,而這些如果使用屬性的形式會非常多,不利於實際開發。而且,EF Core可以通過 Assembly 方式整體載入配置文件。再者,為了保證ORM中的O不受其他因素的影響。也就是說,如果使用註解形式配置映射關係,那麼勢必會造成影響。

當然了,使用配置文件必然會導致項目的類增多,而且大量的重覆類可能會出現。當然了,如果考慮到這個問題的話,可以試試寫一個項目代碼生成器哦,專門用來處理這些差不多的類。

咳咳,總而言之,使用配置文件利大於弊,所以我推薦使用配置文件對關係進行配置。

2. 數據變化

換句話說,嗯,也就是增刪改。在數據增刪這兩方面,EF Core沒有太多需要註意的地方。不過如果有導航屬性的話,在新增的時候,EF Core會自動檢索導航屬性的另一端是否需要新增到資料庫中,如果需要新增的話,EF Core會自動標記為新增的。

而刪除,如果在配置導航屬性時,沒有設置級聯刪除,刪除當前元素,如果另一端的外鍵是可空類型的,並不會刪除導航屬性另一端的元素只會設置外鍵指向為NULL,如果另一端外鍵是不可空的,那麼就會同時刪除。如果需要修改,可以使用以下方法修改,在配置導航屬性的時候:

OnDelete(DeleteBehavior.Cascade);

對於可為NULL的外鍵來說,枚舉DeleteBehavior的值起以下作用:

行為名稱 對記憶體中的依賴項/子項的影響 對資料庫中的依賴項/子項的影響
Cascade 刪除實體 刪除實體
ClientSetNull(預設) 外鍵屬性設置為 null None
SetNull 外鍵屬性設置為 null 外鍵屬性設置為 null
Restrict None None

而對於不可為NULL的外鍵來說,枚舉DeleteBehavior的值起以下作用:

行為名稱 對記憶體中的依賴項/子項的影響 對資料庫中的依賴項/子項的影響
Cascade(預設) 刪除實體 刪除實體
ClientSetNull SaveChanges 引發異常 None
SetNull 引發 SaveChanges SaveChanges 引發異常
Restrict None None

而對於數據的修改,EF Core的做法是通過監控實體的ChangeTracker來實現對數據實體的狀態更新。也就是說,如果你從EF Core的上下文獲取了一個實體對象,對這個對象的某些值進行了修改。這時候EF Core其實已經記錄了這個對象的修改。不需要我們額外的調用修改方法(因為根本沒有Update方法)。

EF Core在我們調用 SaveChanges 會把緩存的所有更改(增、刪、改)都推送給資料庫。如果有一條數據變更因為資料庫校驗或者其他約束沒有通過,就會報錯,同時撤銷所有已推送的變更並取消後續變更的推送。

從資料庫的角度來看,EF Core在SaveChanges的過程中是以事務的形式推送給資料庫的。如果出錯,那麼事務就會回滾。

所以一般情況下,EF不需要開啟事務。

3.花樣查詢

EF Core 支持Linq查詢,所以在查詢的時候可以使用Linq進行。簡單示例如下:

var context = new DefaultContext("Data Source=demo.db");
var results = from t in context.Set<SingleTargetModel>()
			 select t;

當然,也可以使用方法鏈的形式傳入一個Expression<Func<T,bool>> 類型的表達式。

var results = context.Set<SingleTargetModel>().Where(t=>true);

看到這裡了,可能會有疑問了,這明明很簡單呀。是的,如果只是查詢,自然簡單。

那麼,結合排序、分頁之後呢?先來看看排序是怎麼實現的吧。

在查詢表達式寫法中,排序應該這樣的寫的:

var results = from t in context.Set<SingleTargetModel>()
		    orderby t.Id //descending 如果降序則取消註釋
	    	select t ;

方法鏈的形式是:

var results = context.Set<SingleTargetModel>().Where(t=>true).OrderBy(t=>t.Id);

分頁只能通過方法鏈的形式進行分頁,這裡提供一個分頁的工具方法:

public static IQueryable<T> Paging<T>(IQueryable<T> source,int pageIndex,int pageSize)
{
    return source.Skip(pageSize * (pageIndex - 1)).Take(pageSize);
}

這裡用到的是 Skip(int count) 表示忽略數據集的前count條記錄,Take(int count)取得數據集的前count條記錄。

EF Core在調用 ToList的時候,會將已調用的方法和Linq轉換成SQL語句,並正式向資料庫發起查詢。如果出現了在Linq中調用三方方法或者自己寫的工具方法的話,可能會提示不受支持。

如果使用的Linq表達式,則沒關係,EF Core在遇到這種情況的時候,會把資料庫里所有數據都載入到上下文中,再執行後續的查詢等操作。

所以,為了高效的查詢,在執行查詢的時候,最好使用簡單的查詢條件。

4. 後續

EF Core整體使用已經介紹完了,當然照例是普通工程級的內容。下一篇我給大家介紹一下EF Core剩下一些邊角料,嗯。如果要深挖代碼的話,得以後有機會了。

數據訪問系列,EF Core 篇即將到一段落。待EF Core篇完成後,將帶領一起去探索 Nhibernate和Dapper,SqlSugar這三個ORM框架。

更多內容煩請關註我的博客《高先生小屋》

file


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我看到 "這篇文章" 之後自己嘗試了一下還是找不到對應的call,畢竟沒有學習過逆向,只是因為一時興起想逆向一下微信。 找到關鍵CALL 不過我找到了一個投機取巧的辦法:因為已經知道了微信的二維碼圖片是PNG格式的,而PNG有一個通用的文件頭,如下 我們可以利用這個找到記憶體中的二維碼圖片,然後對它下 ...
  • 目標:在win10系統上安裝linux虛擬機,並ssh登陸。 第一步:安裝虛擬機 在實際工作中,通常需要多台伺服器,這時候通過虛擬軟體,將一臺主機分割模擬成多個伺服器是很好的選擇。 在這裡我使用VirtualBox虛擬軟體來創建虛擬機,官方網址:https://www.virtualbox.org/ ...
  • ​ 如果想看更多技術好書,可以關註微信公眾號【程式員書單】作者黃小斜,目前是阿裡Java工程師,業餘時間廣泛讀書,在公眾號里除了分享程式員必讀的技術書籍之外,也會推薦很多關於個人成長、投資理財等方面的書籍。你煩惱的每個問題,書中都有答案。 在這裡,我們將為你推薦幫助程式員以及互聯網從業者自我提升的各 ...
  • 啟言:每個函數定義都有鏈接器可識別的獨一無二的編譯後的函數名稱 種類:C 語言鏈接性、C++ 語言鏈接性,可能有如下的編譯器翻譯 spiff( int ) _spiff // C spiff( int ) _spiff_i // C++ (函數重載) spiff(double, double) _s ...
  • SunnyUI.Net, 基於 C# .Net WinForm 開源控制項庫、工具類庫、擴展類庫、多頁面開發框架 Blog: https://www.cnblogs.com/yhuse Gitee: https://gitee.com/yhuse/SunnyUI GitHub: https://git ...
  • 過程很簡單,傳遞ViewModel到附加屬性,附加屬性引發相關事件和取消事件,從而引發VM中的委托。 修正版本2 2020年5月19日 07點03分 徹底一模一樣了,和之前寫的。 不過更順了 添加內容 public class AttachModel: Animatable { public sta ...
  • 最近公司很多業務都要求上雲,雲上的資料庫購買了mysql(估計是應為便宜吧),所以我用abp框架開發的應用都要逐步切換到mysql。經過一陣摸索踩坑,總算是切換成功了,所以先記錄下方便後續切換使用,也順便分享給有需要的朋友。 一、集成MySQL 其實集成mysql主要是參照官方文檔進行就可以了(官方 ...
  • 上一篇文章(https://www.cnblogs.com/meowv/p/12896898.html)已經成功將博客項目跑起來了,那麼本篇主要是將之前遺留的問題解決,現在的代碼看起來可能還是比較混亂,有大量與之無關的代碼存在裡面,對於強迫症患者來說真的是零容忍。 在程式員界,總有一批強迫症患者,他 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...