Как обработать ноль в LINQ Subquery? - PullRequest
3 голосов
/ 25 мая 2009

У меня есть подзапрос, который возвращает самое последнее значение из дочерней таблицы. В некоторых случаях подзапрос ничего не возвращает. Приведенный ниже запрос не выполняется во время выполнения, поскольку предполагаемый тип MemberPrice является десятичным и не имеет значения NULL.

Упрощенный запрос:

Dim q = From s In dc.STOCKs _
        Select s.ID, MemberPrice = _
          (From mp In dc.STOCKPRICEs Where mp.NUMBER = s.NUMBER _
          Order By dc.date Descending _
          Select mp.PRICE).FirstOrDefault

В SQL подзапрос содержал бы Top (1) и возвращал бы Null, когда пуст. Как я могу справиться с этим в LINQ? Есть ли способ сделать MemberPrice обнуляемым или по умолчанию значение равным нулю, если не найдено (или более элегантное решение)?

Большое спасибо, Стюарт

Ответы [ 4 ]

6 голосов
/ 25 мая 2009

Стюарт,

Я изменил поле «Цена» в базе данных, чтобы не допускать пустых значений, и получил ту же ошибку, что и вы:

"Operator '??' cannot be applied to operands of type 'decimal' and 'int'". 

Как вы указали, когда в качестве значения Price установлено недопустимое значение NULL в базе данных, оператор слияния NULL больше не работает, поскольку он ожидает увидеть десятичный тип с пропуском:

decimal?

Если я удаляю оператор слияния null и запускаю контрольный пример, не содержащий цены, я получаю:

"The null value cannot be assigned to a member with type System.Decimal which is a non-nullable value type.."

Вот код, который работает. Ли я привести результат подзапроса к десятичной? перед применением нулевого оператора объединения.

public class Class1
{

    DataClasses1DataContext dc = new DataClasses1DataContext();

    public decimal test(int stockID)
    {

        var q = from s in dc.Stocks
                where s.StockID == stockID
                select new
                {
                    StockID = s.StockID,
                    memberPrice = ((decimal?)(from mp in dc.StockPrices
                                   where mp.StockID == s.StockID
                                   select mp.Price).FirstOrDefault()) ?? 0
                };

        return q.FirstOrDefault().memberPrice;
    }
}
3 голосов
/ 25 мая 2009

Стюарт, попробуйте это:

Dim q = From s In dc.STOCKs _
    Select s.ID, MemberPrice = _
      if((From mp In dc.STOCKPRICEs Where mp.NUMBER = s.NUMBER _
      Order By dc.date Descending _
      Select mp.PRICE).FirstOrDefault),0)

Нулевой оператор объединения объединяет нулевое значение в ноль для MemberPrice.

0 голосов
/ 25 мая 2009

Стюарт,

Вот как я заставил его работать на моей машине. Я прошу прощения за это в C #; прошло слишком много времени с тех пор, как я использовал VB.

Обратите внимание на использование оператора «new» в операторе «select» и использование оператора объединения нулей после FirstOrDefault ().

public class Class1
{

    DataClasses1DataContext dc = new DataClasses1DataContext();

    public decimal MemberPrice(int stockID)
    {

        var q = from s in dc.Stocks
                where s.StockID == stockID
                select new
                {
                    StockID = s.StockID,
                    memberPrice = (from mp in dc.StockPrices
                                   where mp.StockID == s.StockID
                                   select mp.Price).FirstOrDefault() ?? 0
                };

        return q.FirstOrDefault().memberPrice;
    }
}
0 голосов
/ 25 мая 2009

Метод расширения DefaultIfEmpty делает то, что вы ищете?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...