簡體   English   中英

EF Core/Npgsql 參數化整個 where 子句

[英]EF Core/Npgsql Parameterize an entire where clause

我正在嘗試將 Entity Framework Core 與 Npgsql 一起使用來執行原始 SQL 查詢,其中 WHERE 子句部分是從數據庫中提取的,實際“值”由用戶提供。 作為一個具體的例子:

這部分 SQL 是 static

SELECT TITLE as TitleField,
       GEOM as GeomField,
       GEOM_X as XField,
       GEOM_Y as YField
FROM fdw_public."MY_TABLE"

然后管理員可以在數據庫中設置 WHERE 子句,例如:

COLUMNNAME LIKE '%{search}%'

或者

OTHER_COLUMNNAME = '{search}' AND COLUMNNAME = 'Something Static';

這在編譯時是未知的,可能是任何有效的 WHERE 子句。

{search} 部分是一個占位符。 我相信來自數據庫的子句,這僅由應用程序所有者控制,如果他們想破壞自己的表,那很好。

最終結果是這個 SQL

SELECT TITLE as TitleField,
       GEOM as GeomField,
       GEOM_X as XField,
       GEOM_Y as YField
FROM fdw_public."MY_TABLE"
WHERE COLUMNNAME LIKE '%{search}%'

然而,{search} 部分是用戶輸入(來自 web 應用程序),因此需要參數化。

以下工作,但顯然對 SQL 注入非常開放

var sql = $@"SELECT TITLE as TitleField,
                    GEOM as GeomField,
                    XFIELD as XField,
                    YFIELD as YField
             FROM fdw_public."MY_TABLE"
             WHERE {searchDefinition.WhereClause.Replace("{search}", searchTerm)}";
            
var dbResults = _context.DatabaseSearchResults.FromSqlRaw(sql).ToList();

所以我嘗試為整個 where 子句使用一個參數

var sql = $@"SELECT TITLE as TitleField,
                    GEOM as GeomField,
                    XFIELD as XField,
                    YFIELD as YField
             FROM fdw_public."MY_TABLE"
             WHERE @whereClause";

        var whereClauseParam = new Npgsql.NpgsqlParameter("@whereClause", searchDefinition.WhereClause.Replace("{search}", searchTerm));
        var dbResults = _context.DatabaseSearchResults.FromSqlRaw(sql,whereClauseParam).ToList();

但這會從 Npgsql 引發以下異常

42804:WHERE 的參數必須是類型 boolean,而不是類型文本

這對我來說確實很有意義,因為對整個子句進行參數化感覺是錯誤的,但我想不出更好的方法來解決它。

理想情況下,我只需要對搜索詞進行參數化,就像這樣

var sql = $@"SELECT TITLE as TitleField,
                    GEOM as GeomField,
                    XFIELD as XField,
                    YFIELD as YField
             FROM fdw_public."MY_TABLE"
             WHERE {searchDefinition.WhereClause.Replace("{search}","@p0")}";

            var searchTermParam = new Npgsql.NpgsqlParameter("p0", searchTerm);
            var dbResults = _context.DatabaseSearchResults.FromSqlRaw(sql, searchTermParam).ToList();

但同樣,這是行不通的,這是可以理解的,因為它是按字面解釋的。

我覺得這可能會改變我完全這樣做的方式,或者更糟糕的是,使用一些眾所周知的清理來清理搜索字符串,但我不想這樣做,我想使用參數。

無論哪種方式,總而言之,要求是這樣的

  • WHERE 子句必須來自數據庫,但可以信任
  • db 中的 WHERE 子句可以是任何帶有 {search} 占位符的有效 WHERE,允許我們執行通配符之類的操作(管理員應該知道數據類型以及值是否應該用引號括起來等)
  • 必須對搜索詞進行清理

嘗試將"{search}"替換為"{0}"並將searchTerm作為parameters傳遞給FromSqlRaw


var sql = $@"SELECT TITLE as TitleField,
                    GEOM as GeomField,
                    XFIELD as XField,
                    YFIELD as YField
             FROM fdw_public.""MY_TABLE""
WHERE {searchDefinition.WhereClause.Replace("{search}","{0}")}";

var dbResults = _context.DatabaseSearchResults.FromSqlRaw(sql, searchTerm).ToList();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM