Как заказать IQueryable со значением null в .net core 3.1

#entity-framework #asp.net-core #ef-core-3.1

Вопрос:

На главной странице моего магазина есть список IQueryable, который меняется с помощью различных фильтров. Теперь, например, если цена со скидкой равна нулю, результат на момент заказа будет равен ошибке. Я вставил часть кода …

 IQueryable<Group> result = _context.Groups
            .Include(c => c.Product)
            .Include(c => c.ProductGroup);
 

В приведенном ниже коде выходные данные получаются с помощью другой службы

 switch (getType)
        {
            case "all":
                break;
            case "discountPrice":
                result = IsDiscountedProductsByGroups(result);
                break;
        }
 

Ошибка видна ниже при попытке заказать. После этого шага будут применены другие фильтры, а затем заполнена модель представления, и возвращаемое значение-Кортеж.

 if (getType == "discountPrice")
        {
            switch (orderByType)
            {
                case "date":
                    {
                        result = result.OrderByDescending
                            (p => p.Product.CreateDate)
                            .ThenBy(p => p.Product.TireDiameter.Code);
                        break;
                    }
                case "lowPrice":
                    {
                        result = result.OrderBy(p => p.Product.PurchasePrice)
                            .ThenBy(p => p.Product.TireDiameter.Code);
                        break;
                    }
                case "highPrice":
                    {
                        result = result.OrderByDescending(p => p.Product.PurchasePrice)
                            .ThenBy(p => p.Product.TireDiameter.Code);
                        break;
                    }
            }
        }
 

Отредактированный вопрос:

Добавлен раздел:

Друзья, которые прокомментировали это, похоже, подумали, что продукты могут быть не по цене. Но я должен сказать «нет». Цена указана со скидкой, но может начинаться или заканчиваться. По этой причине, когда этот список отправляется в следующую службу, он дает нулевой ответ и при заказе возникнет ошибка:

 public IQueryable<Group> IsDiscountedProductsByGroups(IQueryable<Group> groups)
    {

        foreach (var item in groups)
        {
            if (item.Product.PurchasePrice != null)
            {
                if (item.Product.StartDiscountTime != null amp;amp; item.Product.StartDiscountTime < DateTime.Now)
                {
                    if (item.Product.EndDiscountTime != null amp;amp; item.Product.EndDiscountTime > DateTime.Now)
                    {
                        listDiscountedProductsByGroup.Append(item);
                    }
                }
            }
        }
        return listDiscountedProductsByGroup;
    }
 

Ответ №1:

Если вы хотите включить продукты, на которые могут быть или не быть цены, и рассматривать товары без цен как 0 (или любое другое значение), попробуйте что-то вроде этого:

 result.OrderBy(p => p.Product.PurchasePrice.HasValue ? p.Product.PurchasePrice.Value : 0);
 

Если вы хотите, чтобы они были помещены в конец списка, вы можете использовать очень большое магическое число вместо «0» выше или лучше:

 result.OrderBy(p => p.Product.PurchasePrice.HasValue ? 0 : 1)
    .ThenBy(p => p.Product.PurchasePrice.HasValue ? p.Product.PurchasePrice.Value : 0);
 

Это позволит упорядочить те, у которых есть цена, по цене, а затем переместить те, у которых нет цены, в конец.

Если вы хотите исключить продукты, у которых нет закупочных цен, вам нужно использовать Where предложение для их фильтрации.

 result.Where(p => p.Product.PurchasePrice.HasValue)
     .OrderBy(p => p.Product.PurchasePrice.Value);
 

Обновление: хорошо, основываясь на вашей обновленной реализации, есть пара проблем:

#1. из вашего примера неясно, где объявлена listDiscountedProductsByGroup.

#2. Похоже, в вашей логике сравнения дат есть ошибка, из-за которой ожидается, что как начало, так и конец скидки будут меньше, чем сейчас. Обычно это было бы Начало <= сейчас amp;amp; Конец >= сейчас.

#3. ваш метод «IsDiscountedProductsByGroups» принимает EF IQueryable и потенциально вернет материализованный набор сущностей, которые могут быть IQueryable, но больше не будут выводиться в SQL, а будут обрабатываться в памяти. Это не такая большая проблема, если все, что вы делаете, — это применяете сортировку, но если вы хотите применить любую другую фильтрацию или разбить результаты на страницы с Skip помощью/ Take , это нарушает оптимизацию EF для отправки в SQL.

Вместо этого, возможно, это то, что вы ищете:

 IQueryable<Group> result = _context.Groups
        .Include(c => c.Product)
        .Include(c => c.ProductGroup);

if (getType == "discountPrice")
{
    var now = DateTime.Now;
    result = result.Where(x => x.Product.PurchasePrice != null
        amp;amp; x.Product.StartDiscountTime.HasValue 
        amp;amp; x.Product.StartDiscountTime < now
        amp;amp; x.Product.EndDiscountTime.HasValue 
        amp;amp; x.Product.EndDiscountTime > now);
}
 

… затем отсюда добавьте соответствующий заказ. Это гарантирует IQueryable , что EF останется под вопросом.

Это предполагает, что вам нужны только товары, у которых есть Товар со скидкой, под которую сегодня подпадает. Это выглядит немного странно, хотя, поскольку я ожидал бы, что у продукта будет больше истории цен, или идея скидок будет отслеживаться отдельно.

Комментарии:

1. Ваше объяснение было полным, но, к сожалению, вы неправильно поняли мой вопрос. Вопрос был исправлен

2. Я добавил обновление, которое может охватывать сценарий, который, по-видимому, пытается реализовать ваш обновленный пример.

Ответ №2:

Попробуйте это:

 result = result.OrderByDescending(p => p.Product.PurchasePrice.HasValue)
 

Комментарии:

1. Добавлено, но я не видел никаких изменений, и я все еще вижу ошибку