У меня есть Form
с ComboBox
и TextBox
. Первый содержит имена столбцов, второй содержит текст для поиска. В качестве источника ComboBox
берет ListTypeSearch
из элементов ItemSearch
. В обработке нажатия кнопки Поиск
вызывается метод Search()
.
Если дать имя столбца так, то ничего не найдется
EF.Functions.Like(item.Value, ...); // Value = "FullName"
Если указывать столбец из модели, поиск работает
EF.Functions.Like(w.FullName, ...);
Можно ли в рамках одного метода Search()
подменять столбец по которому должен идти поиск?
ListTypeSearch.Add(new ItemSearch { Value = "FullName", Display = "ФИО" });
ListTypeSearch.Add(new ItemSearch { Value = "PassportSeries", Display = "Серия" });
ListTypeSearch.Add(new ItemSearch { Value = "PassportNumber", Display = "Номер" });
public class ItemSearch
{
public string Value { get; set; }
public string Display { get; set; }
}
internal List<WorkerTableRow> Search(ItemSearch item, string text)
{
try
{
Found = new List<WorkerTableRow>();
using (ModelContext model = new ModelContext())
{
Found = (from w in model.Workers
where EF.Functions.Like(w.FullName, // этот код
String.Format("%{0}%", text))
select new WorkerTableRow
{
...
})
.ToList();
}
}
catch (Exception ex) { ... }
return Found;
}
Update
Сделал следующим образом. Это можно упростить? Может C#
умеет сам возвращать свойства по имени.
where EF.Functions.Like(w.GetProperty(item.Value),
String.Format("%{0}%", text))
public partial class Workers
{
...
public string FullName { get; set; }
public string PassportSeries { get; set; }
public string PassportNumber { get; set; }
public string GetProperty(string name)
{
switch (name)
{
case "FullName":
return FullName;
case "PassportSeries":
return PassportSeries;
case "PassportNumber":
return PassportNumber;
default:
return string.Empty;
}
}
}
Я включил логирование запросов и посмотрел, что генерируется в том и другом случае.
Если использовать Like(w.FullName, ...)
, то получается следующий запрос:
Executed DbCommand (94ms) [Parameters=[@__Format_1='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
SELECT [w].[WorkerId], [w].[FullName], [w].[PassportNumber], [w].[PassportSeries]
FROM [Workers] AS [w]
WHERE [w].[FullName] LIKE @__Format_1
Видно, что в WHERE
используется LIKE
и передаётся параметр.
Если использовать Like(w.GetProperty(item.Value), ...)
, то получается следующее:
The LINQ expression 'where __Functions_0.Like([w].GetProperty(__item_1), __Format_2)' could not be translated and will be evaluated locally.
Executed DbCommand (47ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [w].[WorkerId], [w].[FullName], [w].[PassportNumber], [w].[PassportSeries]
FROM [Workers] AS [w]
Во-первых, выдаётся предупреждение, что метод GetProperty
не может быть транслирован в sql и будет выполнен локально.
Во-вторых, в самом запросе отсутствует WHERE
и нет параметров.
Вообще, EF Core известен тем, что по умолчанию выполняет на клиенте те действия, которые не может транслировать в sql на сервере. Это может приводить к вытягиванию большого объёма данных и снижения производительности.
Breaking changes included in EF Core 3.0 - в этой статье написано, что в EF Core 3 поведение изменится и станет таким же, как в обычном EF: если запрос не может быть транслирован в действия на сервере, то будет выброшено исключение. А если кому-то всё же нужно продолжить выполнение linq-запроса локально, всегда можно вызвать AsEnumerable()
.
Решение:
List<WorkerTableRow> Search(ItemSearch item, string text)
{
string pattern = string.Format("%{0}%", text);
using (var model = new ModelContext())
{
IQueryable<Worker> query = model.Workers;
if (item.Value == "FullName")
query = query.Where(w => EF.Functions.Like(w.FullName, pattern));
if (item.Value == "PassportSeries")
query = query.Where(w => EF.Functions.Like(w.PassportSeries, pattern));
if (item.Value == "PassportNumber")
query = query.Where(w => EF.Functions.Like(w.PassportNumber, pattern));
return query.Select(w => new WorkerTableRow { ... }).ToList();
}
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Использую дженерик репозиторий в проекте и и не могу понять как реализовать редактирование модели? Использую adonet и нигде не могу найти информацию...
У меня есть асинхронная функция, она возвращает результатИногда он мне нужен, иногда нет
Необходимо вывести индексы начала и конца последовательности дублирующихся гласных символов