#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(...)
для уже выбранных объектов