原始 SQL 查詢 (EF6)

Entity Framework 可讓您使用 LINQ 搭配您的實體類別進行查詢。 不過,有時候您可能想要對資料庫直接使用未經處理的 SQL 來執行查詢。 這包括呼叫預存程式,這對目前不支援對應至預存程式的 Code First 模型很有説明。 本主題所示範的技巧同樣適用於使用 Code First 和 EF 設計工具所建立的模型。

撰寫實體的 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 查詢

傳回任何類型實例的 SQL 查詢,包括基本類型,都可以使用 Database 類別上的 SqlQuery 方法來建立。 例如:

using (var context = new BloggingContext())
{
    var blogNames = context.Database.SqlQuery<string>(
                       "SELECT Name FROM dbo.Blogs").ToList();
}

即使物件是實體類型的實例,資料庫上的 SqlQuery 傳回的結果永遠不會受到內容追蹤。

將原始命令傳送至資料庫

使用 Database 上的 ExecuteSqlCommand 方法,可以將非查詢命令傳送至資料庫。 例如:

using (var context = new BloggingContext())
{
    context.Database.ExecuteSqlCommand(
        "UPDATE dbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1");
}

請注意,使用 ExecuteSqlCommand 對資料庫中資料所做的任何變更都與內容不透明,直到從資料庫載入或重載實體為止。

輸出參數

如果使用輸出參數,則除非完整讀取結果,否則其值將無法使用。 這是因為 DbDataReader 的基礎行為,請參閱 使用 DataReader 擷取資料以取得詳細資料。