дерево выражений лямбда не может содержать нулевой оператор распространения

Вопрос: Цена линии price = co?.price?? 0, price = co?.price?? 0, в следующем коде приведена приведенная выше ошибка. но если я удалю ? от co.? он отлично работает. Я пытался следовать этому примеру MSDN, где они используются ? on line select new { person.FirstName, PetName = subpet?.Name?? String.Empty }; select new { person.FirstName, PetName = subpet?.Name?? String.Empty }; Значит, мне нужно понять, когда использовать ? с ?? и когда не нужно.

Ошибка:

дерево выражений лямбда не может содержать нулевой оператор распространения

public class CustomerOrdersModelView
{
    public string CustomerID { get; set; }
    public int FY { get; set; }
    public float? price { get; set; }
    ....
    ....
}
public async Task<IActionResult> ProductAnnualReport(string rpt)
{
    var qry = from c in _context.Customers
              join ord in _context.Orders
                on c.CustomerID equals ord.CustomerID into co
              from m in co.DefaultIfEmpty()
              select new CustomerOrdersModelView
              {
                  CustomerID = c.CustomerID,
                  FY = c.FY,
                  price = co?.price ?? 0,
                  ....
                  ....
              };
    ....
    ....
 }

Ответ 1

Пример, который вы цитировали, использует LINQ to Objects, где неявные лямбда-выражения в запросе преобразуются в делегаты... тогда как вы используете EF или аналогичные, с IQueryable<T> queryies, где лямбда-выражения преобразуются в выражение деревья. Деревья выражений не поддерживают нулевой условный оператор (или кортежи).

Просто сделайте это по-старому:

price = co == null ? 0 : (co.price ?? 0)

(Я считаю, что оператор с нулевым коалесцированием отлично в дереве выражений.)

Ответ 2

Код, на который вы ссылаетесь, использует List<T>. List<T> реализует IEnumerable<T> но не IQueryable<T>. В этом случае проекция выполняется в памяти и ?. работает.

Вы используете IQueryable<T>, который работает по-разному. Для IQueryable<T> создается представление проекции, и ваш поставщик LINQ решает, что с ним делать во время выполнения. Для соображений обратной совместимости, ?. не могут быть использованы здесь.

В зависимости от вашего провайдера LINQ вы можете использовать plain . и до сих пор не получить NullReferenceException.