简体   繁体   English

如何使用 dapper 构建动态参数化查询?

[英]How to build dynamic parameterised query using dapper?

How to build dynamic parameterised query using dapper?如何使用 dapper 构建动态参数化查询?

I have columns and their values in KeyValuePair我在 KeyValuePair 中有列及其值

eg例如

Key   | Value
------| -------
FName | Mohan
LName | O'reily
Gender| Male

I want to build dynamic SQL statement using dapper and execute it,我想使用 dapper 构建动态 SQL 语句并执行它,

    string statement = "SELECT * FROM Employee WHERE 1 = 1 ";
    List<KeyValuePair<string,string>> lst = new List<KeyValuePair<string,string>>();
    lst.Add(new KeyValuePair<string,String>("FName","Kim"));
    lst.Add(new KeyValuePair<string,String>("LName","O'reily"));
    lst.Add(new KeyValuePair<string,String>("Gender","Male"));
    foreach(var kvp in lst)
    {
        statement += " AND "+ kvp.Key +" = '"+ kvp.Value +"'";
    }
    using (var connection = _dataAccessHelper.GetOpenConnection())
    {
      try
      {
           //CommandDefinition cmd = new CommandDefinition(statement);

           var searchResult = await connection.QueryAsync<dynamic>(statement);

Above query fails because there is special character in query.上述查询失败,因为查询中有特殊字符。
I found that for parameterised statements CommandDefinition can be used,我发现可以使用参数化语句CommandDefinition

how to use CommandDefinition to execute the above statement without any error?如何使用CommandDefinition执行上述语句而没有任何错误?
or或者
is there any better way to build dynamic sql statements?有没有更好的方法来构建动态sql语句?

Don't build the query as text.不要将查询构建为文本。 You can use the Dapper SqlBuilder, it goes something like this:您可以使用 Dapper SqlBuilder,它是这样的:

List<KeyValuePair<string,string>> lst = new List<KeyValuePair<string,string>>();
lst.Add(new KeyValuePair<string,String>("FName","Kim"));
lst.Add(new KeyValuePair<string,String>("LName","O'reily"));
lst.Add(new KeyValuePair<string,String>("Gender","Male"));
var builder = new SqlBuilder();
var select = builder.AddTemplate("select * from Employee /**where**/");
foreach (var kvPair in lst)
{
    builder.Where($"{kvPair.Key} = @{kvPair.Key}", new { kvPair.Value });
}
using (var connection = _dataAccessHelper.GetOpenConnection())
{
    try
    {
        var searchResult = await connection.QueryAsync<dynamic>(select.RawSql, select.Parameters);
    }
    ...

You should never try to escape parameters yourself, leave it to Dapper.你永远不应该试图自己转义参数,把它留给 Dapper。 Then you will also be protected against SQL-injection.然后,您还将受到保护,免受 SQL 注入的影响。

DapperQueryBuilder is an alternative to Dapper SqlBuilder and would work like this: DapperQueryBuilder是 Dapper SqlBuilder 的替代品,其工作方式如下:

List<KeyValuePair<string,string>> lst = new List<KeyValuePair<string,string>>();
lst.Add(new KeyValuePair<string,String>("FName","Kim"));
lst.Add(new KeyValuePair<string,String>("LName","O'reily"));
lst.Add(new KeyValuePair<string,String>("Gender","Male"));

using (var connection = _dataAccessHelper.GetOpenConnection())
{
    var query = connection.QueryBuilder($@"SELECT * FROM Employee");

    foreach(var kvp in lst)
        query.Where(${kvp.Key:raw} = {kvp.Value}";

    var searchResult = await query.QueryAsync<YourPOCO>();
}

The output is fully parametrized SQL ( WHERE FName = @p0 AND LName = @p1 etc ).输出是完全参数化的 SQL( WHERE FName = @p0 AND LName = @p1 etc )。

You just have to be aware that strings which you interpolate using raw modifier are not passed as parameters (because you can't pass a column as a parameter), and therefore you should ensure that the "Keys" (column names) are safe.您只需要注意使用raw修饰符插入的字符串不会作为参数传递(因为您不能将列作为参数传递),因此您应该确保“键”(列名称)是安全的。 The other strings (Values in your case) look like regular (unsafe) string interpolation but they are converted to parameters.其他字符串(在您的情况下为值)看起来像常规(不安全)字符串插值,但它们被转换为参数。

Disclaimer: I'm one of the authors of this library免责声明:我是这个库的作者之一

There is no reason to use a list of key value pairs to build an SQL statement with dynamic parameters.没有理由使用键值对列表来构建带有动态参数的 SQL 语句。 You can simply put placeholders in the query, for example @FName from the example above, and provide the values for those placeholders as the second parameter of QueryAsync method by passing in an anonymous type with its keys corresponding to the placeholders and values to the dynamic values that you want to use for the query.您可以简单地将占位符放在查询中,例如上面示例中的@FName ,并通过将匿名类型及其与占位符对应的键和值传递给动态来提供这些占位符的值作为 QueryAsync 方法的第二个参数要用于查询的值。

string statement = "SELECT * FROM Employee WHERE FName=@FName AND LName=@LName AND Gender=@Gender";
...
var searchResult = await connection.QueryAsync<dynamic>(statement, new { FName = "Kim", LName = "O'reily", Gender="Male" });

You can use the DynamicParameters class for generic fields.您可以将DynamicParameters类用于泛型字段。

Dictionary<string, object> Filters = new Dictionary<string, object>();
Filters.Add("UserName", "admin");
Filters.Add("Email", "admin@admin.com");
var builder = new SqlBuilder();
var select = builder.AddTemplate("select * from SomeTable /**where**/");
var parameter = new DynamicParameters();
foreach (var filter in Filters)
{
    parameter.Add(filter.Key, filter.Value);
    builder.Where($"{filter.Key} = @{filter.Key}");                        
}


var searchResult = appCon.Query<ApplicationUser>(select.RawSql, parameter);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM