推薦關注「碼俠江湖」加星標,時刻不忘江湖事
這是 EF Core 系列的第五篇文章,上一篇文章盤點了 EF Core 中的幾種數據查詢方式。
但是有有時候,我們可能無法用標準的 LINQ 方法完成查詢任務。
或者編譯后的 LINQ 查詢,沒有我們想要的那么高效;又或者我們想要調用一個存儲過程。
這些情況下,我們希望可以編寫原始 SQL 語句,讓 EF Core 去執行。
因此,這篇文章就簡要的講一講如何在 EF Core 中使用原始 SQL 語句進行查詢。
點擊上方或后方藍字,閱讀 EF Core 系列合集。
FromSqlRaw
讓我們來看一個簡單的示例:
var?account?=?_context.Accounts.FromSqlRaw(@"SELECT?*?FROM?Account?WHERE?Name?=?{0}",?"Zilor").FirstOrDefault();
FromSqlRaw
方法允許我們將原始 SQL 語句,添加到 EF Core 查詢中。
還可以執行存儲過程:
var?account?=?_context.Accounts.FromSqlRaw("EXECUTE?dbo.MyCustomProcedure").ToList();
需要注意的是 FromSqlRaw
方法有一些限制:
結果中的列名,必須與屬性被映射到的列名相匹配
查詢必須為實體或查詢類型的所有屬性返回數據
SQL 查詢不能包含導航關系,但我們總是可以把
FromSqlRaw
和Include
方法結合起來。
如果想在查詢中包含導航關系,可以這樣做:
var?account?=?_context.Accounts.FromSqlRaw("SELECT?*?FROM?Account?WHERE?Name?=?{0}",?"Zilor").Include(e?=>?e.AccountSubjects).FirstOrDefault();
ExecuteSqlRaw
FromSqlRaw
可以執行原始 SQL 語句查詢,但不能執行插入、刪除、更新等 SQL 語句,這需要使用 ExecuteSqlRaw
方法實現,比如這樣:
var?rowsAffected?=?_context.Database.ExecuteSqlRaw(@"UPDATE?AccountSET?Age?=?{0}?WHERE?Name?=?{1}",20,?"Zilor");
這個方法會返回受影響的行數,無論是從數據庫中更新、插入還是刪除記錄,行為都一樣。
需要注意是,這里我們使用了 Database
屬性,來調用 ExecuteSqlRaw
方法
而在之前的例子中,我們都是使用 Account
屬性,來調用 FromSqlRaw
方法。
另一件重要的事情是,我們在 FromSqlRaw
和 ExecuteSqlRaw
方法中,都使用了查詢字符串插值功能。
它允許我們在查詢字符串中放置一個變量名,然后 EF Core 會檢查這些參數。
檢查參數的目的,是為了以防止 SQL 注入攻擊。
因此,我們不能在 EF Core 原始 SQL 查詢方法之外,使用字符串插值組裝 SQL 語句。因為,這樣會失去 SQL 參數注入攻擊的檢測。
雖然直接執行 SQL 語句的方式比較直接,但缺點就是在代碼中直接操作數據庫的方式,不符合 ORM 的編程模式與思想。
如果我們直接操作數據庫表,那么就無法利用 EF Core 強類型的特性。
如果實體模型發生改變,那么必須手動變更 SQL 語句。
而且如果調用了一些某些數據庫特有的語法和函數,那么一旦程序遷移到其他數據庫,就可能需要重新編寫 SQL 語句。
這樣也就無法利用 EF Core 強大的 SQL 翻譯機制,來屏蔽不同底層數據庫的差異。
所以,在能不用的情況下,最好不要使用執行原生 SQL 語句的功能。
重新加載
假設我們有一個已經加載的實體,然后使用 ExecuteSqlRaw
方法,對數據庫中的實體做了一些修改,那此時我們加載的實體肯定是過時。
比如這樣:
var?accountForUpdate?=_context.Accounts.FirstOrDefault(s?=>?s.Name.Equals("Zilor"));var?rowsAffected?=_context.Database.ExecuteSqlRaw(@"UPDATE?AccountSET?Age?=?{0}WHERE?Name?=?{1}",22,?accountForUpdate.Name);
只要我們執行這個查詢,數據庫中的 Age
就會變成 22
。
但 accountForUpdate
對象中的 Age
屬性則不會改變,盡管它在數據庫中已經被改變了。
所以,現在的問題是,如果我們想讓它在執行 ExecuteSqlRaw
方法后,實體對象的值隨之改變,該怎么辦?。
其實很簡單,我們只需要在 SQL 語句執行完成后,使用 Reload
方法重新加載這個實體即可:
_context.Entry(accountForUpdate).Reload();
小結
這篇文章主要講了 EF Core 的原始 SQL 語句查詢,下篇文章講繼續講述 EF Core 的數據修改。
更多精彩內容,請關注我▼▼
如果喜歡我的文章,那么
在看和轉發是對我最大的支持!
(戳下面藍字閱讀)
ASP.NET 6 中間件系列
查缺補漏系統學習 EF Core 6? 系列
推薦關注微信公眾號:碼俠江湖
? ? ? ? ? ? ? ? ? ? ? ??覺得不錯,點個在看再走喲