Условное включение Entity Framework ()

avatar
Ghazi Gassara
7 апреля 2018 в 23:20
216
2
1
public partial class Table
{   
    public int TableId { get; set; }
    public Nullable<int> Num { get; set; }
    public int NbSeats { get; set; }
    public Nullable<int> R_LocationId { get; set; }
    public virtual ICollection<Availibility> Availibilities { get; set; }
    public virtual R_Locations R_Locations { get; set; }
}

public partial class Availibility
{
    public System.DateTime DayRes { get; set; }
    public Nullable<bool> Available { get; set; }
    public int TableId { get; set; }
    public virtual Table Table { get; set; }
}

Я хотел бы реализовать этот запрос с Entity Framework:

select * 
from Tables join Availibilities 
    on Availibilities.TableId = Tables.TableId 
where Availibilities.Available=1
Источник
Nikhil Vartak
7 апреля 2018 в 23:52
1

Возможный дубликат условного включения() в Entity Framework

Ответы (2)

avatar
Jonathan Magnan
9 апреля 2018 в 13:48
0

Существует два способа включения объекта в фильтр.

  • Использование проекции (см. ответ @Harald)
  • Использование сторонней библиотеки

Отказ от ответственности: я являюсь владельцем проекта Entity Framework Plus ( EF+ Query IncludeFilter позволяет легко фильтровать включенные сущности. Работает с EF6.x

return context.Tables
                .IncludeFilter(x => x.Availibilities .Where(c => c.Available == 1))
                .ToList();

Под капотом библиотека делает именно проекцию.

Одним ограничением является все Include, но теперь он вызывается с помощью IncludeFilter, даже если не указан фильтр, такой как учетная запись.

Wiki: EF+ Query Include Filter

avatar
Harald Coppoolse
9 апреля 2018 в 10:52
0

Одним из наиболее медленных этапов выборки данных из базы данных является транспортировка данных из СУБД в локальный процесс. Следовательно, вы не должны передавать больше значений, чем вы фактически планируете использовать.

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

Итак, если у вас есть таблица с идентификатором 4, которая имеет 100 Availabilities, и вы бы запросили Table с его Availabilities, используя Join и Include, вы бы передали доступность внешнего ключа. TableId a 100 раз, хотя вы уже знаете, что все они будут иметь значение Table.Id. Вы даже знаете это значение, потому что запросили таблицу с идентификатором 4.

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

Вернуться к вашему вопросу

Учитывая tableId, вам нужна информация о таблице вместе с (некоторыми или всеми) ее доступностями.

Благодаря структуре сущностей вам не нужно использовать Join. Если вы используете коллекции, инфраструктура сущностей выполнит объединение за вас.

var tableWithAvailabilities = myDbContext.Tables
    .Where(table => table.TableId == tableId)
    .Select(table => new
    {
         // select only the properties you plan to use
         Id = table.TableId,
         Num = table.Num,
         ...
         Availabilities = table.Availabilities
             .Where(availability => ...) // if you don't want all Availabilities
             .Select(availability => new
             {
                 // again: select only the properties you plan to use

                 // not needed, you know it equals Table.TableId
                 // Id = availability.TableId,

                 Date = availability.DayRes,
                 Available = availability.Avialable,
             })
             .ToList(),
    });

Структура Entity знает, какое соединение необходимо для этого. Одна из приятных вещей при использовании коллекций вместо соединения заключается в том, что вы делаете свою базу данных более абстрактной: вы действительно думаете о Table, у которого есть ноль или более Availabilities. Недостаток СУБД в том, что для реализации этого ей нужны две таблицы. Если ваши внутренние таблицы изменятся, например, имя внешнего ключа, ваш запрос не изменится, потому что вы не используете внешний ключ

Если вы не планируете обновлять полученное значение, то вряд ли имеет смысл выполнять выборку