我试图将表名作为参数传递给ExecuteSql()
方法。
这是我尝试过的:
var viewName = "search_view";
using (var db = dbFactory.Open())
{
db.ExecuteSql("REFRESH MATERIALIZED VIEW @viewName;", new { viewName });
}
它不起作用,它通过以下消息创建异常:
Npgsql.PostgresException
42601:“ $ 1”或附近的语法错误
我启用了日志记录以尝试查看生成了什么SQL,但是我认为由于异常,该查询未记录。
当查询全部为文本时,查询运行正常,将表名作为参数传递时我做错了什么?
答案 0 :(得分:2)
您只能使用数据库参数代替参数,即,您不能像尝试使用的那样将它们用作SQL模板生成的自由文本替代。
您需要在SQL中使用包含viewName
,例如:
db.ExecuteSql($"REFRESH MATERIALIZED VIEW {viewName};");
尽管如果用户提供了viewName
,则需要防止可能的SQL注入。我的建议是对照允许的viewNames白名单进行检查,例如:
if (!AllowedViewNames.Contains(viewName))
throw new Exception("Invalid View");
在OrmLite中,您可以使用GetQuotedValue()
API对字符串进行转义,例如:
var quotedViewName = db.GetDialectProvider().GetQuotedValue(viewName);
要检测符号(如视图名称)的无效名称,可以使用RegEx只允许有效字符,例如:
if (!new Regex(@"[^A-Za-z0-9_]").IsMatch(viewName))
throw new Exception("Invalid View");
使用OrmLite的SqlVerifyFragment()
扩展方法,如果您想接受SQL片段,则可以检测到潜在的非法SQL注入,例如:
db.ExecuteSql($"SELECT * FROM User WHERE {userSql.SqlVerifyFragment()}");
如果OrmLite检测到潜在的非法SQL违规,它将在其中抛出ArgumentException
。