Я занимаюсь практическим руководством по mvcmusicstore. Я кое-что заметил при создании скаффолда для менеджера альбомов (добавить, удалить, изменить).
Я хочу писать код элегантно, поэтому я ищу чистый способ написать это.
К вашему сведению, я делаю магазин более общим:
Альбомы = Предметы
Жанры = Категории
Исполнитель = Бренд
Вот как получается индекс (сгенерированный MVC):
var items = db.Items.Include(i => i.Category).Include(i => i.Brand);
Вот как извлекается элемент для удаления:
Item item = db.Items.Find(id);
Первый возвращает все элементы и заполняет категорию и модели бренда внутри модели элемента. Второй, не заполняет категорию и бренд.
Как я могу написать второй, чтобы сделать поиск и заполнить что внутри (желательно в 1 строку) ... теоретически - что-то вроде:
Item item = db.Items.Find(id).Include(i => i.Category).Include(i => i.Brand);
c#
asp.net-mvc
entity-framework
Ральф Н
источник
источник
Ответы:
Include()
Сначала нужно использовать , а затем извлечь один объект из полученного запроса:источник
Деннис ответ использует
Include
иSingleOrDefault
. Последний идет в обход базы данных.Альтернативой является использование
Find
, в сочетании сLoad
, для явной загрузки связанных объектов ...Ниже пример MSDN :
Конечно,
Find
немедленно возвращается без запроса магазина, если этот объект уже загружен контекстом.источник
Find
поэтому, если сущность присутствует, для самой сущности нет обратной передачи в БД. НО, у вас будет круговая поездка для каждого отношения, в котором вы находитесьLoad
, тогда какSingleOrDefault
комбинация сInclude
загрузкой всего за один раз.Load
функцию, отношение должно заполняться при возврате вызова. Так что, если вы звонитеLoad
несколько раз для нескольких отношений, каждый раз будет двусторонняя поездка. Даже для одного отношения, еслиFind
метод не находит сущность в памяти, он выполняет два цикла: один для,Find
а второй дляLoad
. НоInclude
.SingleOrDefault
насколько я знаю, подход извлекает сущность и отношения за один раз (но я не уверен)Вы должны привести IQueryable к DbSet
var dbSet = (DbSet<Item>) db.Set<Item>().Include("");
return dbSet.Find(id);
источник
У меня не сработало. Но я решил это, сделав так.
Не знаю, нормально ли это решение. Но другой, который дал Деннис, дал мне ошибку
.SingleOrDefault(x => x.ItemId = id);
источник
SingleOrDefault(x => x.ItemId = id)
только из-за неправильного сингла=
вместо двойного==
?Там нет действительно простой способ отфильтровать с помощью поиска. Но я придумал близкий способ повторить функциональность, но, пожалуйста, обратите внимание на несколько вещей для моего решения.
Это решение позволяет вам выполнять общую фильтрацию, не зная первичного ключа в .net-core
Поиск принципиально отличается, поскольку он получает сущность, если она присутствует в отслеживании, перед запросом базы данных.
Кроме того, он может фильтровать по объекту, поэтому пользователю не нужно знать первичный ключ.
Это решение для EntityFramework Core.
Вот несколько методов расширения, которые помогут вам фильтровать по первичному ключу, поэтому
Когда у вас есть эти методы расширения, вы можете фильтровать так:
источник