Entity Framework 允許你用 LINQ 查詢你的實體類別。 不過,有時你可能會想直接用原始 SQL 對資料庫執行查詢。 這包括呼叫儲存程序,對於目前不支援映射到儲存程序的 Code First 模型來說,這很有幫助。 本主題中展示的技術同樣適用於使用 Code First 與 EF Designer 所建立的模型。
為實體撰寫 SQL 查詢
DbSet 上的 SqlQuery 方法允許撰寫原始 SQL 查詢,回傳實體實例。 回傳的物件會像用 LINQ 查詢一樣,透過上下文被追蹤。 例如:
using (var context = new BloggingContext())
{
var blogs = context.Blogs.SqlQuery("SELECT * FROM dbo.Blogs").ToList();
}
請注意,就像 LINQ 查詢一樣,查詢不會執行直到結果被列舉出來 — 在上述範例中,這是透過呼叫 ToList 方法來完成。
撰寫原始 SQL 查詢時應謹慎,原因有兩個。 首先,查詢應確保只回傳真正屬於請求型態的實體。 例如,使用繼承等特性時,很容易寫出查詢,產生錯誤 CLR 類型的實體。
其次,某些類型的原始 SQL 查詢會暴露潛在的安全風險,尤其是針對 SQL 注入攻擊。 請確保你在查詢中正確使用參數,以防範此類攻擊。
從儲存程序載入實體
你可以使用 DbSet.SqlQuery 從儲存程序的結果中載入實體。 例如,以下程式碼在資料庫中呼叫 dbo.GetBlogs 程序:
using (var context = new BloggingContext())
{
var blogs = context.Blogs.SqlQuery("dbo.GetBlogs").ToList();
}
你也可以使用以下語法將參數傳給儲存程序:
using (var context = new BloggingContext())
{
var blogId = 1;
var blogs = context.Blogs.SqlQuery("dbo.GetBlogById @p0", blogId).Single();
}
撰寫非實體類型的 SQL 查詢
可透過資料庫類別的 SqlQuery 方法,回傳任意類型(包括原始型別)的 SQL 查詢。 例如:
using (var context = new BloggingContext())
{
var blogNames = context.Database.SqlQuery<string>(
"SELECT Name FROM dbo.Blogs").ToList();
}
即使物件是實體類型的實例,從資料庫 SqlQuery 回傳的結果也不會被上下文追蹤。
將原始指令傳送到資料庫
非查詢指令可透過資料庫上的 ExecuteSqlCommand 方法傳送至資料庫。 例如:
using (var context = new BloggingContext())
{
context.Database.ExecuteSqlCommand(
"UPDATE dbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1");
}
請注意,使用 ExecuteSqlCommand 對資料庫中資料所做的任何變更,在從資料庫載入或重新載入實體之前,對上下文是不透明的。
輸出參數
若使用輸出參數,其值在結果完整讀取後無法取得。 這是因為 DbDataReader 的底層行為,詳情請參見 「使用 DataReader 檢索資料 」。