SqlParameter:Resharper 的格式字符串中未使用参数

SqlParameter: Argument is not used in format string from Resharper

在我的 VS 2017 上安装 Resharper 后,我在 SqlParameter 参数上收到此警告。

Argument is not used in format string

var children = context.FluxoHierarchy
    .FromSql("get_children_fluxo_closure @node_id", new SqlParameter("@node_id", queueItem.ProximoNode)).ToList();

resharper 向我提出的解决方案是删除冗余参数。

var children = context.FluxoHierarchy
    .FromSql("get_children_fluxo_closure @node_id").ToList();

我的代码有问题吗?

这里的问题是字符串文字被翻译为 RawSqlString 如果您将鼠标悬停在 FromSql.

上,您可以在方法签名中看到它

消除警告的解决方法是为您的查询使用字符串变量。

string query = "get_children_fluxo_closure @node_id";
var children = context.FluxoHierarchy
    .FromSql(query, new SqlParameter("@node_id", queueItem.ProximoNode))
    .ToList();

此警告的原因是 FromSql 您正在使用的重载使用特殊的 Resharper 属性修饰,StringFormatMethodAttribute。这个属性

Indicates that the marked method builds string by the format pattern and (optional) arguments. The parameter, which contains the format string, should be given in constructor. The format string should be in System.String.Format(System.IFormatProvider,System.String,System.Object[])-like form.

因此,FromSql 签名如下所示:

[StringFormatMethod("sql")]
public static IQueryable<TEntity> FromSql<TEntity>(this IQueryable<TEntity> source, RawSqlString sql, params object[] parameters)

其中 sql 是格式模式,parameters 是格式字符串的参数,正如 Resharper 认为的那样,因为上述属性。

然后 Resharper 发现您的格式字符串中没有任何位置参数(位置参数如 {0}{1} 等 - 您将用于 String.Format 的内容) ,并看到您传递了一个参数。它正确地(因为属性)认为这个参数是无用的,因为格式字符串不包含任何占位符。它希望你像这样使用它(比如 String.Format):

FromSql("get_children_fluxo_closure {0}", 1).ToList();

这也是有效的用法(EF Core 会将 1 转换为参数并替换它,因此它不是 SQL 注入)。

但是如您所知,同样的方法支持另一种传递参数的方式,您正在使用的一种方式。但是,Resharper 无法知道这一点。方法用 StringFormatMethod 属性装饰,Resharper 再次正确地假设它总是这样使用。

所以这个问题不在 Resharper 方面,而是在 EF Core 方面,因为混合不同的参数传递方式,然后用属性装饰方法,迫使 Resharper 认为只有一个是有效的,这不是一个好主意。那还不如干脆不标。

要解决此问题,您可以使用 "string-format" 方式传递参数,如上所示,但这当然并不总是可取的。您可以通过将查询移动到单独的变量或执行类似以下操作来阻止 Resharper 分析此表达式:

FromSql(new RawSqlString("get_children_fluxo_closure @node_id"), new SqlParameter("@node_id", 1)).ToList();

或通过注释禁用警告:

// ReSharper disable once FormatStringProblem
FromSql("get_children_fluxo_closure @node_id", new SqlParameter("@node_id", 1)).ToList();

但这一切都很丑陋。真正的解决方案是在 EF Core github 跟踪器上打开一个问题并要求他们修复它。