Почему метод с запросом перестаёт работать?
Я в ListView записываю результат запроса, он работает . Выводит все те данные которые мне необходимо
Но в событии tbPoisk_TextChanged возникает исключение
System.NotSupportedException: "Выражению LINQ to Entities не удается распознать метод "Boolean ListViewDate(System.String)", поэтому его нельзя преобразовать в выражение хранилища."
Почему метод в событии не хочет коректно работать ?
public BookPage()
{
InitializeComponent();
ListViewDate(sql);
}
const string sql = "SELECT * FROM books " +
"WHERE NOT EXISTS(SELECT NULL " +
"FROM Extraditions " +
"WHERE Extraditions.IdBook = Books.Id " +
"AND Extraditions.IdStatus <> 2)";
public bool ListViewDate(string sql)
{
var book = App.DataBase.Books.
SqlQuery(sql).ToList();
listBook.ItemsSource = book;
return true;
}
private void tbPoisk_TextChanged(object sender, TextChangedEventArgs e)
{
if (!string.IsNullOrEmpty(tbPoisk.Text))
{
try
{
listBook.ItemsSource = App.DataBase.Books.Where(p => ListViewDate(sql) && (
p.NameBook.ToString().ToLower().Contains(tbPoisk.Text.ToLower()) ||
p.AuthorOfThebook.ToString().ToLower().Contains(tbPoisk.Text.ToLower()) ||
p.YearOfPublication.ToString().ToLower().Contains(tbPoisk.Text.ToLower()))).ToList();
var rows = listBook.ItemsSource.Cast<Book>().ToList();
if (rows.Count == 0)
{
tbInfo.Visibility = Visibility.Visible;
}
if (rows.Count != 0)
{
tbInfo.Visibility = Visibility.Collapsed;
}
}
catch
{
tbInfo.Visibility = Visibility.Collapsed;
MessageBox.Show("Ошибка в получении данных", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
else
{
try
{
tbInfo.Visibility = Visibility.Collapsed;
ListViewDate(sql);
}
catch
{
tbInfo.Visibility = Visibility.Collapsed;
MessageBox.Show("Ошибка в получении данных", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
Ответы (2 шт):
Проблема возникает потому, что фильтрация выполняется по App.DataBase.Books, то есть по EF-запросу, а не по уже загруженному списку. В итоге LINQ to Entities пытается преобразовать выражение в SQL, но не знает, что такое ваш метод, и выдаёт ошибку.
Чтобы избежать этого, нужно сначала загрузить данные в память, а затем выполнять фильтрацию уже по списку, а не по EF-контексту:
private void tbPoisk_TextChanged(object sender, TextChangedEventArgs e)
{
if (!string.IsNullOrEmpty(tbPoisk.Text))
{
// Загружаем данные один раз
var books = App.DataBase.Books.SqlQuery(sql).ToList();
// Фильтруем по списку в памяти
var filtered = books.Where(p =>
p.NameBook.ToLower().Contains(tbPoisk.Text.ToLower()) ||
p.AuthorOfThebook.ToLower().Contains(tbPoisk.Text.ToLower()) ||
p.YearOfPublication.ToString().Contains(tbPoisk.Text)
).ToList();
listBook.ItemsSource = filtered;
tbInfo.Visibility = filtered.Count == 0 ? Visibility.Visible : Visibility.Collapsed;
}
else
{
ListViewDate(sql); // исходная загрузка данных
tbInfo.Visibility = Visibility.Collapsed;
}
}