Как я могу использовать лямбда-функцию в методе FindAsync()?

#c# #asp.net #entity-framework #linq #entity-framework-core

#c# #asp.net #entity-framework #linq #сущность-фреймворк-ядро

Вопрос:

Я хочу найти объекты, соответствующие определенному требованию. В этом случае я хочу, чтобы атрибут className класса Course был равен «course». Оператор, который я хотел использовать, был:

 Course matchingCourse = collection.FindAsync(x => x.className == "course");
 

Атрибут className не является первичным ключом, поэтому я не могу просто вставить ключ.

Из этого я получаю сообщение об ошибке «Невозможно преобразовать лямбда-выражение в тип ‘object’, поскольку оно не является типом делегата». Я огляделся и не могу понять, как решить проблему в этом контексте.

Как я могу использовать лямбда-функцию для выполнения того, что я пытаюсь сделать в FindAsync(), или есть другой способ?

Ответ №1:

Вы можете использовать a Where , за которым следует FirstOrDefault или SingleOrDefault или просто передать им предикат, если вам не нужен кеш, который Find вам дает. Это будет вызывать базу данных каждый раз. Find работает только с первичными ключами.

Например:

 Course matchingCourse = collection.FirstOrDefault(x => x.className == "course");
 

Для асинхронности:

 Course matchingCourse = await collection.FirstOrDefaultAsync(x => x.className == "course");
 

Ответ №2:

Основное различие между Find и Select заключается в том, что Find сначала проверяет, был ли извлечен нужный вам объект ранее с момента создания DbContext . Select всегда будет извлекать данные из базы данных.

Фактически, функция Find используется, если вы извлекли объект, потеряли ссылку на него и хотите снова получить выбранный объект, а не оригинал.

Обычно не рекомендуется поддерживать DbContext в рабочем состоянии в течение длительного времени, поэтому вероятность того, что вы потеряете ссылку на выбранный объект, очень мала.

Поэтому я бы посоветовал использовать Select для извлечения элемента:

(исключая асинхронность, это не часть вашей проблемы)

 var result = collection
    .Where(collectionElement => collectionElement.ClassName == "course")
    .FirstOrDefault();
 

Если вам действительно нужно получить ранее выбранный элемент, вы можете использовать DbContext.ChangeTracker.Entries<...>() и выполнить a Where(...) для уже выбранных объектов