Тип приведения в LINQ .include выражение C# - ICollection в IEnumerable - PullRequest
0 голосов
/ 13 июля 2020

Я не уверен, имеет ли этот вопрос смысл. Но знает ли кто-нибудь, возможно ли приведение типов внутри выражения .include в лямбда-выражение LINQ.

var Items = _context.Items
        .Include(c => c.ItemCategorys)
        .ToList();

The navigation property is declared like an ICollection "public ICollection<ItemCategory> ItemCategorys { get; set; }"

Вопрос в том, могу ли я преобразовать тип ICollection в IEnumerable в операторе «.include» .

Я безуспешно пробовал

var Items = _context.Items
        .Include(c => c.ItemCategorys.AsEnumerable())
        .ToList();

и

var Items = _context.Items
        .Include(c => c.ItemCategorys as IEnumerable<ItemCategorys>)
        .ToList();

1 Ответ

0 голосов
/ 15 июля 2020

Вы должны понимать, для чего предполагается использовать include.

Согласно спецификациям, QueryableExtensions.Include будет включать полностью указанное свойство. Довольно часто люди используют это как сокращение для «выбрать все свойства».

Предположим, у вас есть простое отношение «один ко многим» между школами и учащимися: в каждой школе ноль или более учеников, каждый ученик посещает ровно одна школа, а именно школа, к которой относится внешний ключ.

Если в школе [110] 2000 учеников, то каждый ученик школы [10] будет иметь внешний ключ со значением 10. Если вы используете Включить чтобы получить School [10] с учениками, вы передадите это же значение 10 более 2000 раз. Какая трата вычислительной мощности!

Было бы гораздо разумнее использовать Select для выборки данных:

var schools = dbContext.Schools.Select(school => new
    {
        // Select only the School properties that you plan to use
        Id = school.Id,
        Name = school.Name,
        ...

        Students = school.Students.Select(student => new
        {
            // again: only the properties that you plan to use
            Id = student.Id,
            Name = student.Name,
            ...

            // not needed, you know the value
            // SchoolId = student.SchoolId,
        })
        .ToList(),
    });

В Entity framework всегда используйте Select для запроса данных и выбора только свойства, которые вы планируете использовать. Используйте include только в том случае, если вы планируете изменить извлеченные данные.

Не используйте Include, чтобы не набирать текст.

Преимущество Select заключается в том, что вы можете возвращать данные, которые отличается от ваших исходных данных, а это именно то, что вам нужно.

Вы хотите получить «несколько свойств Items, каждый элемент с перечисляемой последовательностью нескольких свойств его ItemCategories»

var result = dbContext.Items.Select(item => new
{
    Id = item.Id,
    Name = item.Name,
    ...

    ItemCategories = item.ItemCategories.Select(category => new
    {
        Id = category.Id,
        ...
    });
})

Обратите внимание, что ItemCategories - это IQueryable некоторого анонимного типа. Если вы хотите, чтобы это было IEnumerable<ItemCategory>, используйте .Select(category => new ItemCategory и заполните только те свойства, которые вы планируете использовать.

Результатом будет IQueryable<ItemCategory>.

  • Положительный результат: если вызывающий абонент хочет только несколько категорий ItemCategories, вы не получите их все.
  • Отрицательный: вам придется поддерживать dbContext в активном состоянии до тех пор, пока не будут выбраны все желаемые элементы.

Проблема в том, что пользователи не будут знать, какие свойства у вас есть, а какие нет. Чтобы преодолеть это, люди склонны отделять внутреннюю структуру данных (= ваши классы в DbSet) от данных, которые вы предоставляете другим:

.Select(category => new ExternalCategory()
{
     Id = category.Id,
     ...
});

Хорошая вещь в этом методе заключается в том, что вы можете давать разные доступ пользователей к различным значениям: некоторые пользователи получают данные только с помощью свойств получения, у других есть методы для обновления данных, а суперпользователи имеют доступ к таблицам изменений.

Также: путем отделения структуры базы данных от данных, которые другие могут доступа, вы сможете вносить небольшие изменения в базу данных, не меняя пользователей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...