Ядро Entity Framework — нет

Я пытаюсь воспроизвести оператор SQL в EF Core, но не могу найти способ сделать это, чтобы установить сцену. У меня есть следующая структура таблицы.

Слот -> SlotInstance -> SlotInstanceUser (Слот может иметь много SlotInstances, SlotInstance может иметь много SlotInstanceUsers)

Когда пользователь регистрируется для SlotInstance, в SlotInstanceUsers создается запись, в которой хранятся SlotInstanceId и UserId — все хорошо.

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

    SELECT
        S.StartDate, S.EndDate, S.StartTime, S.EndTime, S.DayOfWeek,
        SI.Date
    FROM
        Slot S WITH (NOLOCK)
    INNER JOIN
        SlotInstance SI WITH (NOLOCK) ON S.Id = SI.SlotId
    WHERE
        SI.ID not in (  
                        SELECT 
                            SlotInstanceId 
                        FROM 
                            SlotInstanceUser SIU WITH (NOLOCK) 
                        WHERE 
                            SIU.UserId = @UserID
                    )   
    ORDER BY
        SI.Date

Но я просто не могу воспроизвести это в ядре EF - что мне не хватает?

Вы хотите использовать Join LINQ или хотите выполнять свой SQL с помощью EF Core?

Mohi 23.04.2022 16:46

Я хочу иметь возможность реплицировать SQL с помощью EF Core, если это возможно, если нет, я просто создам хранимую процедуру и вызову ее. Это скорее SI.ID NOT IN (...), который я хотел реплицировать, не является проблемой.

CoderK 23.04.2022 17:03
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
2
2
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете написать запрос LINQ почти так же, как запрос SQL. Только помните, что в LINQ select стоит последним, переменные (псевдонимы) обязательны, а эквивалентом SQL NOT IN является !Contains. например

var query =
from s in db.Slots
join si in db.SlotInstances on s.Id equals si.SlotId
where !(from siu in db.SlotInstanceUsers
        where siu.UserId == userId)
        select siu.SlotInstanceId).Contains(si.Id)
orderby si.Date
select new
{
    s.StartDate, s.EndDate, s.StartTime, s.EndTime, s.DayOfWeek,
    si.Date       
};

Но в EF Core у вас есть больше возможностей, особенно для объединений, поскольку обычно отношения (и связанные с ними объединения) инкапсулируются со свойствами навигации. Таким образом, модель, которую вы описываете словами в терминах EF Core/C#, выглядит примерно так:

public class Slot
{
    public int Id { get; set; }
    // Other properties...
    public ICollection<SlotInstance> SlotInstances { get; set; }
}

public class SlotInstance
{
    public int Id { get; set; }
    // Other properties...
    public Slot Slot { get; set; }
    public ICollection<SlotInstanceUser> SlotInstanceUsers { get; set; }
}

public class SlotInstanceUser
{
    public int Id { get; set; }
    // Other properties...
    public SlotInstance SlotInstance { get; set; }
}

и запрос будет таким

var query =
from s in db.Slots
from si in s.SlotInstances
where !si.SlotInstanceUsers.Any(siu => siu.UserId == userId)
orderby si.Date
select new
{
    s.StartDate, s.EndDate, s.StartTime, s.EndTime, s.DayOfWeek,
    si.Date       
};

(на самом деле это переводится в SQL NOT EXISTS, но это не обязательно).

И если вам не нужна проекция, а просто экземпляры слота (с информацией о слоте), на которые пользователь не зарегистрировался, то это будет просто

var query = db.SlotInstances
    .Include(si => si.Slot)
    .Where(si => !si.SlotInstanceUsers.Any(siu => siu.UserId == userId))

Спасибо за этот ответ, это именно то, что я искал - я использую проекцию, чтобы уменьшить шум, возвращающийся из БД, поскольку он не нужен.

CoderK 23.04.2022 17:19

Другие вопросы по теме