2009-05-24 1 views
3

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

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

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 нулевым или по умолчанию значение равно нулю, если не найдено (или более элегантное решение)?

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

+0

Можете ли вы определить, что вы подразумеваете под провалом? FirstOrDefault должен возвращать Nothing, если подзапрос пуст и, следовательно, MemberPrice должен быть 0 в этом случае. – JaredPar

+0

Я получаю System.InvalidOperationException {«Нулевое значение не может быть присвоено члену с типом System.Decimal, который является типом значения, не имеющим значения NULL."}. Я также ожидал, что он вернет 0, если null, поэтому я должен что-то упустить. – Stuart

+0

Каков тип mp.PRICE? – JaredPar

ответ

6

Стюарт,

я изменил свою цену поле в базе данных не позволяет аннулирует, и я получил тот же errror вы сделали:

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

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

decimal? 

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

"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; 
    } 
} 
+0

Роберт, большое спасибо за то, что вы перешли за рамки этой проблемы. – Stuart

3

Стюарт, попробуйте следующее:

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

Нулевой коалесцирующий оператор?не существует в vb.net – 2009-05-24 22:51:55

+1

Да, это так: функция If. Как и в If (possibleNullValue, valueIfNull) –

+0

@Robert, я редактировал образец кода, чтобы использовать версию VB.Net для коалесцирующего оператора. – JaredPar

0

Способствует ли метод расширения по умолчаниюIfEmpty делать то, что вы ищете?

+0

Я использовал его для плоских внешних соединений, но не мог понять, как обойтись без назначения значения типа десятичного значения mp.Price. У вас есть идеи по синтаксису, которые я могу попробовать? – Stuart

0

Стюарт,

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

Обратите внимание на использование «нового» оператора в инструкции «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

Я получаю ту же ошибку компилятора с этим кодом в C#, потому что memberPrice выводится как десятичное (vs Nullable ). Ошибка: «Оператор»? не может применяться к операндам типа «десятичный» и «int». Какова цена на вашей машине? – Stuart

+0

Тип Цена на моей машине - Десятичная (18,0) Разрешить Nulls. –

 Смежные вопросы

  • Нет связанных вопросов^_^