将参数传递给ExecuteSql()

时间:2018-09-01 05:21:42

标签: servicestack ormlite-servicestack

我试图将表名作为参数传递给ExecuteSql()方法。

这是我尝试过的:

        var viewName = "search_view";

        using (var db = dbFactory.Open())
        {
            db.ExecuteSql("REFRESH MATERIALIZED VIEW @viewName;", new { viewName });
        }

它不起作用,它通过以下消息创建异常:

  

Npgsql.PostgresException

     

42601:“ $ 1”或附近的语法错误

我启用了日志记录以尝试查看生成了什么SQL,但是我认为由于异常,该查询未记录。

当查询全部为文本时,查询运行正常,将表名作为参数传递时我做错了什么?

1 个答案:

答案 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