Поддерживает ли Dapper подобный оператор?

Использование Dapper-dot-net...

Следующее не дает результатов в объекте данных:

var data = conn.Query(@"
    select top 25 
    Term as Label, 
    Type, 
    ID 
    from SearchTerms 
    WHERE Term like '%@T%'", 
    new { T = (string)term });

Однако, когда я просто использую обычный формат строки, например:

string QueryString = String.Format("select top 25 Term as Label, Type, ID from SearchTerms WHERE Term like '%{0}%'", term);
var data = conn.Query(QueryString);

Я получаю 25 строк обратно в коллекцию. Dapper неправильно анализирует конец параметра @T?


person Jay Stevens    schedule 17.05.2011    source источник


Ответы (5)


Пытаться:

term = "whateverterm";
var encodeForLike = term => term.Replace("[", "[[]").Replace("%", "[%]");

string term = "%" + encodeForLike(term) + "%";
var data = conn.Query(@"
   select top 25 
  Term as Label, 
  Type, 
  ID 
  from SearchTerms 
  WHERE Term like @term", 
  new { term });

В подобных операторах нет ничего особенного, вам никогда не нужны ваши параметры внутри строковых литералов, они не будут работать, вместо этого они будут интерпретироваться как строка.

примечание

Жестко закодированный пример во втором фрагменте настоятельно не рекомендуется, помимо того, что это огромная проблема с sql-инъекцией, он может привести к утечке dapper.

предостережение

Любое совпадение like, которое начинается с подстановочного знака, не подлежит SARG, что означает, что оно медленное и потребует сканирования индекса.

person Sam Saffron    schedule 17.05.2011
comment
Сэм - пытаюсь заставить ваш ответ работать в моем проекте, но выдает ошибки. почему вы устанавливаете термин перед тем, как объявить его строкой? Мне нужен только % справа от термина в запросе. Я пытался сделать: string formattedTerm = searchTerm + [[]%[]]; но он не возвращает результатов. - person jpshook; 29.07.2011
comment
Сэм, возможно, стоит ответить ему. Меня это тоже смутило - person RobVious; 09.04.2015
comment
.Replace([, [[]).Replace(],[]]) — это неправильно. Однако убедитесь, что вы избегаете предложения like: stackoverflow.com/questions/439495/ - person razon; 21.04.2015
comment
Примечание: этот подход уязвим для атак SQL-инъекций, проверьте ответ Atir для лучшего подхода. - person Leo; 26.09.2018

Лучший способ использовать это, чтобы добавить функцию concat в запрос, поскольку она также сохраняется при внедрении sql, но функция concat поддерживается только выше, чем sql 2012

string query = "SELECT * from country WHERE Name LIKE CONCAT('%',@name,'%');"
var results = connection.query<country>(query, new {name});
person Atir Naveed    schedule 16.03.2016
comment
Вы также можете использовать '+' вместо CONCAT, например: SELECT * from country WHERE Name LIKE '%' + @name + '%'; - person jhhwilliams; 09.04.2018

Да. Это простое решение работало для меня каждый раз:

db.Query<Remitente>("SELECT * 
                     FROM Remitentes 
                     WHERE Nombre LIKE @n", new { n = "%" + nombre + "%" })
                   .ToList();
person eliaquin    schedule 12.02.2017
comment
Это ответ, который мне больше всего понравился ... простой и прямой - person oliverdejohnson; 12.02.2019
comment
Это определенно мой фаворит — я также использую интерполяцию строк, поэтому она становится ... new { n = $%{nombre}% } - person Chad Carter; 10.04.2021
comment
идеально! Сделал из него метод ext - person ihorbond; 09.05.2021

Ответ Сэма у меня не работал, поэтому после некоторого тестирования я придумал использовать эквивалент SQLite CONCAT, который, кажется, работает:

string sql = "SELECT * FROM myTable WHERE Name LIKE '%' || @NAME || '%'";
var data = IEnumerable data = conn.Query(sql, new { NAME = Name });
person Dscoduc    schedule 25.07.2016

Просто чтобы отвлечься от ответа Сэма, вот как я создал два вспомогательных метода, чтобы немного упростить поиск с помощью оператора LIKE.

Во-первых, при создании метода для генерации параметризованного запроса этот метод использует dynamic: , но создание строго типизированного универсального метода должно быть более желательным во многих случаях, когда вам нужна статическая типизация вместо динамической.

public static dynamic ParameterizedQuery(this IDbConnection connection, string sql, Dictionary<string, object> parametersDictionary)
{
    if (string.IsNullOrEmpty(sql))
    {
        return null;
    }
    string missingParameters = string.Empty;
    foreach (var item in parametersDictionary)
    {
        if (!sql.Contains(item.Key))
        {
            missingParameters += $"Missing parameter: {item.Key}";
        }
    }
    if (!string.IsNullOrEmpty(missingParameters))
    {
        throw new ArgumentException($"Parameterized query failed. {missingParameters}");
    }
    var parameters = new DynamicParameters(parametersDictionary);
    return connection.Query(sql, parameters);
}

Затем добавьте метод для создания поискового запроса Like, который будет работать с Dapper.

public static string Like(string searchTerm)
{
    if (string.IsNullOrEmpty(searchTerm))
    {
        return null;
    }
    Func<string, string> encodeForLike = searchTerm => searchTerm.Replace("[", "[[]").Replace("%", "[%]");
    return $"%{encodeForLike(searchTerm)}%";
}

Пример использования:

var sql = $"select * from products where ProductName like @ProdName";
var herringsInNorthwindDb = connection.ParameterizedQuery(sql, new Dictionary<string, object> { { "@ProdName", Like("sild") } });

foreach (var herring in herringsInNorthwindDb)
{
    Console.WriteLine($"{herring.ProductName}");
}

И мы получаем наши образцы данных из базы данных Northwind:
Пример данных

Мне нравится этот подход, поскольку мы получаем вспомогательные методы расширения для выполнения повторяющейся работы.

person Tore Aurstad    schedule 28.06.2021