Husain Ahmad Khalid Ответов: 2

Простой T-SQL в LINQ


У меня есть простой SQL-оператор, как показано ниже:
Select s.StaffID, s.FirstName + ' ' + s.LastName as FullName from Staff s 
left outer join CheckIn c on c.StaffID = s.StaffID
WHERE s.ContractStatusID=1 and c.CheckInID is null

Оператор SQL работает нормально, теперь я хочу написать для него запрос LINQ, я пробовал это сделать, но это не тот путь:
var db = new SREntities();
            var all = from s in db.Staffs
                      join c in db.CheckIns on s.StaffID equals c.StaffID into ps
                      from c in ps.DefaultIfEmpty()
                      where s.ContractStatusID == 1  && c.CheckInID == null
                      select new { s.StaffID, FullName = s.FirstName + " " + s.LastName};

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

Заранее спасибо

Что я уже пробовал:

var db = new SREntities();
            var all = from s in db.Staffs
                      join c in db.CheckIns on s.StaffID equals c.StaffID into ps
                      from c in ps.DefaultIfEmpty()
                      where s.ContractStatusID == 1  && c.CheckInID == null
                      select new { s.StaffID, FullName = s.FirstName + " " + s.LastName};

Maciej Los

Что не так с вашей версией SQL-оператора Linq?

Husain Ahmad Khalid

он не дает требуемого результата, он не возвращает никакого значения

Maciej Los

Не можете ли вы использовать Кроме? Я имею в виду все из стола персонала, кроме тех людей, которые зарегистрировались ;)

Husain Ahmad Khalid

давайте попробуем

2 Ответов

Рейтинг:
4

Jon McKee

В ответе Мацея нет ничего плохого, но я думаю, что объяснение того, что пошло не так в вашем примере, может помочь в будущем.

Ваш пример LINQ очень близок - вот правильный запрос:

var query = from staff in db.Staffs
            join checkIn in db.CheckIns on staff.StaffID equals checkIn.StaffID 
              into result
            from r in result.DefaultIfEmpty()
            where staff.ContractStatusID == 1 && (r == null || r.CheckIn == null)
            select new 
            { 
              staff.StaffID, 
              FullName = staff.FirstName + " " + staff.LastName 
            };


При присоединении к группе список результатов всегда существует, даже если он пуст. Обычно эти пустые результаты пропускаются при итерации по результирующему набору. Когда вы используете DefaultIfEmpty() вы устанавливаете эти пустые списки по умолчанию, чтобы всегда иметь сопряжение с левой таблицей (left outer join). Строки для db.CheckIns являются ссылочными типами, хотя их значение по умолчанию null Это означает, что where ... c.CheckIn == null это вызывает проблему, так как вы не можете получить доступ null.CheckIn.

Чтобы справиться с обоими случаями, когда а) результаты пусты и Б) контрольное значение равно нулю, вам необходимо выполнить проверку короткого замыкания. c == null. Это поймает случай, когда список результатов пуст до вы пытаетесь получить доступ к свойству CheckIn, чтобы проверить, является ли оно нулевым.

EDIT: чтобы лучше объяснить групповое соединение, оно работает так, как показано ниже, где каждая строка в левой таблице связана с одним из них:
//Results returned
resultList = new List<T>(); resultList.Add(result1); resultList.Add(result2); //etc...
//No results returned
resultList = null;
//DefaultIfEmpty
resultList = new resultList<T>(); resultList.Add(default(T));


Husain Ahmad Khalid

Спасибо тебе, Джон Макки, так мило с твоей стороны, что ты действительно посвятил свое время ответу на мой вопрос, так мило с твоей стороны

Jon McKee

Никаких проблем! :)

Maciej Los

+5, Джон!
Хорошее объяснение.

Рейтинг:
16

Maciej Los

Способ №1


Как я уже упоминал в комментарии к вопросу вам нужно использовать Кроме метода[^]

var db = new SREntities();
var allCheckedIn = from s in db.Staffs
        join c in db.CheckIns on s.StaffID equals c.StaffID
        select s;

var NotCheckedInOnly = (from s in db.Staffs).Except(allCheckedIn);


Для получения более подробной информации, пожалуйста, смотрите:
Поддерживаемые и неподдерживаемые методы LINQ (LINQ to Entities)[^]
Не в предложении для сущностей[^]

Способ №2


Другой способ достичь этого-использовать Where + Any:
var result = db.Staffs.Where(s=>db.CheckIns.Any(c=>c.StaffID!=s.StaffID));


Попробуй!
Удачи!


Husain Ahmad Khalid

Спасибо Вам, Мацей Лос, я знаю, что вы профессиональный разработчик, но это так мило с вашей стороны посвятить свое время и ответить на мой вопрос, так мило с вашей стороны

Maciej Los

Всегда пожалуйста.
Овации,
Мацей