ASP.NET MVC Linq Query DefaultIfEmpty не работает [дубликат]

У меня была такая же проблема, и я пробовал все, что было опубликовано здесь, чтобы исправить это, но никто не работал для меня. В моем случае я использую Cygwin для компиляции dll. Кажется, что JVM пытается найти JRE DLL на виртуальном пути Cygwin. Я добавил путь виртуального каталога Cygwin к DLL JRE, и теперь он работает. Я сделал что-то вроде:

SET PATH = "/ cygdrive / c / Program Files / Java / jdk1.8.0_45";% PATH%

167
задан paqogomez 18 November 2013 в 22:42
поделиться

7 ответов

Запрос linq-to-sql не выполняется как код, а скорее переведен в SQL. Иногда это «непроницаемая абстракция», которая приводит к неожиданному поведению.

Одним из таких случаев является обработка с нулевым значением, где могут быть неожиданные нули в разных местах. ...DefaultIfEmpty(0).Sum(0) может помочь в этом (довольно простом) случае, когда не может быть элементов, а sql SUM возвращает null, тогда как c # ожидать 0.

. Более общий подход заключается в использовании ?? который будет переведен на COALESCE всякий раз, когда существует риск того, что сгенерированный SQL вернет неожиданный null:

var creditsSum = (from u in context.User
              join ch in context.CreditHistory on u.ID equals ch.UserID                                        
              where u.ID == userID
              select (int?)ch.Amount).Sum() ?? 0;

Это первое приводит к int?, чтобы сообщить компилятору C #, что это выражение действительно может вернуться null, хотя Sum() возвращает int. Затем мы используем обычный ?? оператор для обработки случая null.

Основываясь на этом ответе, я написал сообщение в блоге с подробными сведениями для LINQ to SQL и LINQ для объектов.

289
ответ дан Anders Abel 22 August 2018 в 13:48
поделиться
  • 1
    спасибо Anders, решение с DefaultIfEmpty (0) .Sum () отлично работает для меня. Я также попробовал второе решение с (int?) ... ?? 0 ..., но он вызывает то же исключение, что и раньше. – zosim 28 July 2011 в 20:40
  • 2
    Наконец, обошел, чтобы проверить это и скорректировать его, так что теперь работает и вторая версия. – Anders Abel 11 June 2012 в 22:07
  • 3
    Sum () и другие агрегированные функции возвращают значение null при применении к пустому набору данных. Вопреки их определению, в действительности они возвращают нулевую версию базового типа. – Suncat2000 18 July 2014 в 13:19
  • 4
    @recursive: ваш пример - LINQ-to-Objects, а не LINQ-to-SQL (или LINQ-to-Entities). Их базовые поставщики данных заставляют их вести себя по-разному. – Suncat2000 7 July 2015 в 16:16
  • 5
    Это была хорошая идея. Я обновил свой объект return с нулевыми свойствами и работал как прелесть. – Kremena Lalova 4 August 2015 в 19:30

Это сообщение об ошибке, когда я пытался выбрать из представления.

Проблема заключалась в том, что в последнее время были получены новые новые строки (в столбце SubscriberId), и он не был обновлен в EDMX (Сначала база данных EF).

Столбец должен был иметь тип Nullable для работы.

var dealer = Context.Dealers.Where (x => x.dealerCode == dealerCode ) .FirstOrDefault ();

Перед обновлением просмотров:

public int SubscriberId { get; set; }

После обновления обновления:

public Nullable<int> SubscriberId { get; set; }

Удалено и добавлено представление в EDMX .

Надеюсь, это поможет кому-то.

3
ответ дан 40-Love 22 August 2018 в 13:48
поделиться
  • 1
    Это была моя проблема и мой ответ – Simon Nicholls 1 June 2018 в 16:33

Я вижу, что на этот вопрос уже дан ответ. Но если вы хотите, чтобы он был разделен на два утверждения, можно рассмотреть следующее.

var credits = from u in context.User
              join ch in context.CreditHistory 
                  on u.ID equals ch.UserID                                        
              where u.ID == userID
              select ch;

var creditSum= credits.Sum(x => (int?)x.Amount) ?? 0;
1
ответ дан Lijo 22 August 2018 в 13:48
поделиться

Я использую этот код, и он отвечает правильно, только выходное значение равно NULL.

var packesCount = await botContext.Sales.Where(s => s.CustomerId == cust.CustomerId && s.Validated)
                                .SumAsync(s => (int?)s.PackesCount);
                            if(packesCount != null)
                            {
                                // your code
                            }
                            else
                            {
                                // your code
                            }
1
ответ дан MohammadSoori 22 August 2018 в 13:48
поделиться

Получил эту ошибку в Entity Framework 6 с этим кодом во время выполнения:

var fileEventsSum = db.ImportInformations.Sum(x => x.FileEvents)

Обновление от LeandroSoares:

Используйте это для одиночного исполнения:

var fileEventsSum = db.ImportInformations.Sum(x => (int?)x.FileEvents) ?? 0

Оригинал:

Изменен для этого, а затем он сработал:

var fileEventsSum = db.ImportInformations.Any() ? db.ImportInformations.Sum(x => x.FileEvents) : 0;
0
ответ дан Ogglas 22 August 2018 в 13:48
поделиться
  • 1
    Разве это не выполнило бы это дважды? – nawfal 22 March 2018 в 16:08
  • 2
    Это не очень хороший ответ. Он будет извлекаться из БД дважды. – Leandro Soares 21 June 2018 в 10:10
  • 3
    @nawfal Это правда, но это намного лучше, чем ошибка времени выполнения. Вы можете абсолютно использовать linq-to-sql, но с лямбдой это сложнее. Конечно, вы можете получить исключение, но я думаю, что решение хуже, чем два исполнения. – Ogglas 21 June 2018 в 10:45
  • 4
    @LeandroSoares см. Выше комментарий – Ogglas 21 June 2018 в 10:46
  • 5
    @LeandroSoares Ницца! Я обновил свой ответ и использовал предоставленный вами код и описание, почему его использовать. – Ogglas 21 June 2018 в 11:21

Вы используете функцию aggregate, которая не получает элементы для выполнения действия, вы должны проверить, что запрос linq дает некоторый результат, как показано ниже:

var maxOrderLevel =sdv.Any()? sdv.Max(s => s.nOrderLevel):0
4
ответ дан Prasad Jadhav 22 August 2018 в 13:48
поделиться
  • 1
    Это приведет к тому, что sdv будет выполняться дважды. Это не то, что вы хотите для IQueryables – Ody 20 July 2015 в 13:06

Чтобы разрешить поле с нулевым значением Amount, просто используйте оператор нулевой коалесценции для преобразования нулей в 0.

var creditsSum = (from u in context.User
              join ch in context.CreditHistory on u.ID equals ch.UserID                                        
              where u.ID == userID
              select ch.Amount ?? 0).Sum();
8
ответ дан recursive 22 August 2018 в 13:48
поделиться
  • 1
    когда я использую ваш совет, компилятор говорит: Operator '??' не может применяться к операндам типа 'int' и 'int'. я что-то забыл? – zosim 28 July 2011 в 20:31
  • 2
    @zosim: Именно поэтому сначала добавьте бросок в int?. – Anders Abel 28 July 2011 в 20:44
  • 3
    Я добавил int ?, но то же исключение. Я буду благодарен вам, когда у вас будет dev env. чтобы проверить, что не так в этом синтаксисе. – zosim 28 July 2011 в 20:54
  • 4
    @zosim: Я не понимаю проблему. Если Amount является int, то мы уже уверены, что он не может быть нулевым, и объединение не требуется. Если вы получаете сообщение об ошибке, то Amount не имеет значения NULL, это просто int, и в этом случае, возможно, вам нужно изменить столбец dbml linq2sql в конструкторе, чтобы разрешить null. – recursive 28 July 2011 в 21:14
  • 5
    @recursive: сумма int, все в порядке. Сумма уже имеет значение. Я думаю, что ошибка выше, потому что таблица CreditHistory пуста. У меня есть одна запись в таблице User и 0 записей в таблице CreditHistory и ошибка. Когда я использую DefaultIfEmpty (0) .Sum (), он отлично работает, но с? 0 он выдает ошибку. Мой другой вопрос - это лучшая практика в этом случае? DefaultIfEmpty (0)? благодаря – zosim 28 July 2011 в 21:42
Другие вопросы по тегам:

Похожие вопросы: