Linq 2 Sql Сравнение локальной последовательности с запросом с использованием «Like» – наиболее эффективный метод

Я знаю, что здесь есть несколько подобных вопросов, касающихся сравнения списка с запросом с использованием операции Sql «Like» в качестве компаратора.

Я знаю, что нет прямого перевода с использованием Linq2Sql для такого типа сравнения. То, что предоставленный метод Contains () преобразуется в «IN» в Sql и является точным компаратором. Я также знаю, что неточные методы сравнения (SqlMethods.Like (), String.Contains (), StartsWith () и EndsWith ()) работают только с одним элементом, а не с списком.

В настоящее время у меня есть запрос внутри цикла foreach для обеспечения требуемой функциональности, однако меня беспокоит пропускная способность в моей сети, а также напряжение на сервере БД для больших циклов.

Тогда мой вопрос таков: что является наиболее эффективным методом для выполнения этой операции, минимизируя нагрузку на сеть / сервер?

фрагмент кода моей текущей реализации:

using (var context = new GeoDataContext()) { var originalSuggestions = new List<SuggestItem>(); foreach (var suggestItem in suggestionList) { var item = suggestItem; var placeNameList = context.tl_2014_39_places.Where(placeName => placeName.NAME.Contains(item.Term)).Select( place => place.NAME).ToList(); } } 

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

 CREATE TYPE dbo.StringList AS TABLE (value NVARCHAR(MAX)); 

Затем вы объявляете переменную этого типа (то есть @terms) как DataTable в коде C #, и вы делаете что-то вроде

 select NAME from tl_2014_39_places pl where exists (select 1 from @terms where pl.NAME like '%' + value + '%') 

или присоединитесь к таблице с переменной @terms. Затем выполните SqlCommand, и вы получите результаты в одном запросе. Если вы решите следовать маршрутам сырых sql-запросов, я могу помочь вам найти правильный эффективный запрос (запрос выше – это просто пример того, как он может выглядеть).

ОБНОВЛЕНИЕ: вот полный рабочий образец. Предполагается, что есть таблица tl_2014_39_places со столбцом NAME и что вы создали собственный тип StringList, используя запрос выше:

 private static void Main(string[] args) { var termsTable = new DataTable(); var suggestionList = new List<string>() {"one", "two", "three"}; termsTable.Columns.Add(new DataColumn("value", typeof (string))); foreach (var term in suggestionList) { termsTable.Rows.Add(term); } using (var conn = new SqlConnection(@"data source=(LocalDb)\v11.0;initial catalog=TestDB;integrated security=True;")) { conn.Open(); using (var cmd = new SqlCommand("select NAME from tl_2014_39_places pl where exists (select 1 from @terms where pl.NAME like '%' + value + '%') ", conn)) { cmd.Parameters.Add(new SqlParameter("terms", SqlDbType.Structured) { Value = termsTable, TypeName = "dbo.StringList" }); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { Console.WriteLine(reader[0]); } } } } Console.ReadKey(); } 

Обратите внимание, что в целом LIKE с первым «%» (т.е. «заканчивается» запросами) неэффективны, поскольку для получения результатов требуется сканирование полной таблицы. Но это не связано с вопросом, и, конечно же, он все еще намного эффективнее, чем цикл и несколько запросов db. Вы также можете использовать следующий эквивалентный запрос вместо того, где он существует:

 select NAME from tl_2014_39_places pl inner join @terms t on pl.NAME like '%' + t.value + '%' 

Попробуй это,

Если вы хотите проверить, что у Term есть placeName.NAME

 var placeNameList = context.tl_2014_39_places .Where(placeName => suggestionList .Select(x => x.Term) .Contains(placeName.NAME)) .Select(place => place.NAME).ToList(); 

Если вы хотите проверить placeName.NAME имеет Term

 var placeNameList = context.tl_2014_39_places.AsEnumerable() .Where(placeName => suggestionList.Any(x => placeName.Conaints(x.Term)) .Select(place => place.NAME).ToList(); 

Чтобы избежать поиска с учетом регистра, вы можете использовать ToLower() для обеих строк сравнения, например. placeName.ToLower().Conaints(x.Term.ToLower())

  • Sql Server Query Visualizer - невозможно увидеть сгенерированный SQL-запрос
  • Как подключиться к SQL Server с помощью LINQ to SQL?
  • Производительность Linq: два запроса, первый ответ сразу, а второй - очень медленный
  • Как определить, следует ли использовать join в linq для sql?
  • Лучший тип данных первичного ключа для Linq to SQL
  • Почему повторное использование DataContext отрицательно влияет на производительность?
  • SQL Server дает ошибку «повторного ключа» для свойства без ключа?
  • Получение значения null при конкатенации строки в linq
  • Linq to SQL - Не удалось обновить
  • Как объединить запрос linq динамически?
  • Почему мой запрос Linqued не дает мне правильный результат?
  • Давайте будем гением компьютера.