在 Entity Framework Core 中使用 SQL 語法查詢

在用上 Entity Framework Core 之後,平時基本上都是使用 LINQ (Language Integrated Query) 來查詢資料庫的資料:
    
        string name = "Ruyut";

        var result = _context.Users
            .Where(x => x.Name == name)
            .ToList();
    

但有的時候也會有需要用到 SQL 語法做查詢,並且不能使用 LINQ 語法實踐 (expressed)、或是使用 LINQ 查詢會造成效能低落的情況,是不是就只能使用 SqlConnection 了呢?但這樣就需要取得連接資訊、管理 SqlConnection 的生命週期,最麻煩的是需要將查詢到的結果再映射為 Entity Framework Core 中的實體的資料集合中,想到就很麻煩。

其實 Entity Framework Core 就可以達成這件事情,它有提供基本 SQL 查詢 (Basic SQL queries)功能,能夠使用 FromSqlInterpolated 和 FromSqlRaw 來執行 SQL 語法的查詢。
註1:本文中使用 EF Core 6.0,若使用 EF Core 7.0 或以上則會找不到 FromSqlInterpolated 關鍵字,請使用 FromSql 取代
註2:目前 FromSqlInterpolated 只能讀取一張表的資料,不能組合多張表查詢

FromSqlInterpolated 會自動使用 DbParameter 傳遞參數,所以能夠有效防止 SQL 注入攻擊(SQL injection attacks)
    
        string name = "Ruyut";

        var result = _context.Users
            .FromSqlInterpolated($"select * from users where name = {name}")
            .ToList();
    

註: 使用 FromSqlInterpolated 查詢時 SQL 參數不需要單引號

上面介紹的 FromSqlInterpolated 很安全,但缺點就是無法指定欄位名稱,假設在接受可能發生 SQL 注入攻擊的情況下想要動態決定 SQL ,那可以使用 FromSqlRaw
    
        string name = "Ruyut";
        string columnName = "name";
        
        var result = _context.Users
            .FromSqlRaw($"select * from users where {columnName} = '{name}'")
            .ToList();
    

註: 使用 FromSqlRaw 查詢時 SQL 參數需要單引號,如果沒有包含單引號會出現下面的錯誤:
  
Microsoft.Data.SqlClient.SqlException (0x80131904): 無效的資料行名稱 'Ruyut'。


延伸閱讀: 在 Entity Framework Core 中使用 DbCommand 自由的執行 SQL 語法

參考資料:
SQL Queries

留言