Dapper поддържа ли оператора like?

Използване на 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 съвпадение, което води със заместващ знак, не е SARGable, което означава, че е бавно и ще изисква сканиране на индекса.

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(],[]]) - това е грешно. Уверете се обаче, че избягвате клаузата за харесване: 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 * от страна WHERE Име като '%' + @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
Това със сигурност ми е любимото - използвам и интерполация на низове, така че става ... ново { 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.

Първо, създаване на метод за генериране на параметризирана заявка, този метод използва динамично:, но създаването на строго типизиран общ метод трябва да е по-желателно в много случаи, когато искате статично въвеждане вместо динамично.

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);
}

След това добавяне на метод за създаване на термин за търсене на харесване, който ще работи с 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 DB:
Примерни данни

Харесвам този подход, тъй като получаваме помощни методи за разширение, за да извършваме повтаряща се работа.

person Tore Aurstad    schedule 28.06.2021