Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > LINQ (Language-Integrated Query) > Проблемма с DefaultIfEmpty() |
Автор: BooteR 19.6.2009, 01:16 | ||
Доброго времени суток. Скорее всего проблемма не с DefaultIfEmpty(), а с неумением им пользоваться. Гугл перерыл, ничего похожего не нашел, поэтому спрашиваю тут. Есть несколько табличек в базе. После некоего запроса query получаем таблицу с полями MaterialID и Quantity. Тоесть айди материалла и его необходимое количество. В базе есть таблица Stock. Теперь нужно из query вычесть количество материалов, которое есть на складе. Пробую сделать это таким образом:
Проблемма в том, что если материала нет на складе, то нужно отнимать 0. Без DefaultIfEmpty() оператор First() выдает exception, потому что входящая последовательность пуста. А с DefaultIfEmpty(0) выдает exception " Unsupported overload used for query operator 'DefaultIfEmpty' " Как построить правильно запрос, чтобы небыло проблем когда запись об материале отсутствует в таблице Stock? Помогите, люди добрые! ![]() Наперед спасибо |
Автор: Idsa 19.6.2009, 05:43 |
Попробуйте вместо метода DefaultIfEmpty (который не "замаплен" в LINQ To SQL) воспользоваться методом SingleOrDefault. |
Автор: KelTron 19.6.2009, 06:55 | ||
Разовью идею Idsa.
|
Автор: Idsa 19.6.2009, 06:58 |
KelTron, что есть выражение "?? 0"? |
Автор: KelTron 19.6.2009, 07:01 | ||||
Ну есть такой оператор в шарпе) Ниже два эквивалентных куска кода:
|
Автор: Idsa 19.6.2009, 07:49 |
KelTron, а зачем он здесь? SingleOrDefault, если не найдет запись, вернет 0. |
Автор: KelTron 19.6.2009, 08:18 |
Хм, да, ты прав...как то не обратил внимания, что там не класс. |
Автор: Idsa 19.6.2009, 08:22 | ||
Итого:
KelTron, спасибо за оператор ?? ![]() |
Автор: KelTron 19.6.2009, 09:11 |
На здоровье) |
Автор: BooteR 19.6.2009, 12:16 | ||||
Попробовал с SingleOrDefault():
Получил exception: "The null value cannot be assigned to a member with type System.Int32 which is a non-nullable value type" Причем вот это работает правильно:
В чем проблемма? Я вообще запутался :( |
Автор: Idsa 19.6.2009, 12:34 |
BooteR, приведите схему таблицы Stock |
Автор: BooteR 19.6.2009, 12:45 |
Вот: http://ipicture.ru/ |
Автор: Idsa 19.6.2009, 12:51 |
MaterialId, оказывается, не первичный ключ. Тогда не понимаю смысл этого запроса. Исключение, видимо, вылетает из-за того, что dataContext.GetTable<Stock>().Where(n => n.MaterialID == t.MaterialID) содержит более одного элемента. Раз так, стоит заменить SingleOrDefault на FirstOrDefault. |
Автор: BooteR 19.6.2009, 12:58 |
Я уже не помню почему я не сделал MaterialId первичным ключем, то двух записей с одинаковым MaterialId в таблице нет. Сделал MaterialId первичным ключем, выдает тот же exception. Заменил SingleOrDefault на FirstOrDefault, все та же проблема ![]() Почему же foreach работает нормально? |
Автор: BooteR 19.6.2009, 15:27 | ||
Сделал так:
Некрасиво, но работает. А вообще странно как то... Всем спасибо за помощь! |
Автор: KelTron 19.6.2009, 15:46 | ||
Кажется я понял. Т.к. внешний запрос отложенный => пока ты не начнёшь перечислять коллекцию он не выполнится и значит в поле a.MaterialID будет null. Вложенный запрос же НЕ отложенный и выполняется немедленно, но в это время ещё нет данных об a.MaterialID. Поэтому генерится эксепшин. По этой же причине работает вариант с foreach. Самое простое что приходит в голову для исправления ситуации:
|
Автор: BooteR 19.6.2009, 15:59 |
KelTron, мне результат запроса нужно вывести в DataGridView. Решение с ToList(), как я понимаю, будет проблематично |
Автор: KelTron 19.6.2009, 16:49 | ||
BooteR, не заметил твоего предыдущего сообщения. Хм, что то странное, если у тебя n.Quantity это целое не нулевое число, то каким образом там получается null... Для этого случая как раз и подходит оператор ?? Предыдущий твой код можно написать так:
Что я и предлагал в самом начале... Действительно |
Автор: BooteR 20.6.2009, 01:41 |
KelTron, с оператором ?? я пробовал, но выдает ошибку: Operator '??' cannot be applied to operands of type 'int' and 'int' |