В показанном здесь коде я получаю ошибку в LINQ:
Последовательность не содержит элементов
Когда столбец reason
содержит данные, возникает это исключение. Подскажите пожалуйста, как обработать это исключение.
Код:
if (StudentDetails.rows
.Where(c => string.IsNullOrEmpty(c.reason) && !c.leave)
.Min(c => c.joiningdate) < DateTime.UtcNow.AddDays(-180))
return true;
@TimRoberts, когда причина содержит данные, а значение отпуска ложно, выдается ошибка
Во-первых, это не ответ на вопрос, который вам задали. Если вы имеете в виду, что, по вашему мнению, они существуют, то ответ на вопрос — «да», и именно это вам и следовало сказать. Если вы на самом деле имеете в виду что-то другое, уточните, что это такое.
Почти наверняка нет данных, соответствующих этим критериям, и вы просто думаете, что они есть. Чтобы узнать это, нужно проверить это, что вы уже должны были сделать. Используйте обычный цикл для всех данных и поместите внутри блок if
, который проверяет те же критерии. Затем вы можете поставить точку останова внутри этого блока и посмотреть, будет ли он достигнут. Если это не так, то соответствующих данных нет, и поэтому вы получаете сообщение об ошибке, сообщающее вам об этом. Если он попадет, значит, ваша система сломана, потому что в этом случае LINQ должен работать.
Ваше предложение Where
выбирает все строки, где «причина» пуста, а «оставить» имеет значение false. Если «причина» всегда имеет данные, то КОНЕЧНО, результирующая последовательность не будет содержать элементов.
В показанном здесь коде я получаю ошибку в LINQ:
Последовательность не содержит элементов
На основе вашего общего фрагмента кода и описания я попытался воспроизвести вашу проблему и смог смоделировать возникшую ошибку. Ниже приводится ссылка для вас.
Когда столбец причины содержит данные, возникает это исключение. Подскажите пожалуйста, как обработать это исключение.
Согласно сообщению об ошибке, которое указывает, что это может произойти, если все элементы в StudentDetails.rows
имеют non-null reason
или leave is true
, что приводит к пустой последовательности для работы метода Min.
Таким образом, ваш способ всегда будет сталкиваться с этим исключением, если условие не выполняется.
Чтобы преодолеть исключение, вам следует сначала проверить, есть ли какие-либо элементы в отфильтрованной последовательности, прежде чем вызывать Min. Вы можете использовать метод Любой в Linq, чтобы убедиться, что последовательность не пуста.
Скажем, у меня есть следующий набор данных:
private readonly List<Student> _studentDetails = new List<Student>
{
new Student { reason = "Medical", leave = true, joiningdate = new DateTime(2023, 1, 10) },
new Student { reason = "Personal", leave = true, joiningdate = new DateTime(2022, 2, 15) },
new Student { reason = "Vacation", leave = true, joiningdate = new DateTime(2021, 3, 20) },
new Student { reason = "Disciplinary", leave = false, joiningdate = new DateTime(2023, 4, 1) },
new Student { reason = "Health", leave = true, joiningdate = new DateTime(2021, 5, 30) },
};
Как вы заметили выше, набор данных не выполнил бы условие, в этом случае я бы изменил запрос следующим образом:
var filteredRows = _studentDetails
.Where(c => string.IsNullOrEmpty(c.reason) && !c.leave);
if (filteredRows.Any() && filteredRows.Min(c => c.joiningdate) < DateTime.UtcNow.AddDays(-180))
{
return Ok(true);
}
Итак, в filteredRows
сначала присваивается результат метода Where
, фильтрующего строки на основе ваших условий. Затем метод Any
используется для проверки того, содержит ли filteredRows
какие-либо элементы. Только если filteredRows
не пусто, вызывается метод Min для поиска минимума joiningdate
, и исключение больше не выдается.
Выход:
Примечание. Пожалуйста, обратитесь к этому официальному документу, если вам нужна дополнительная информация.
Ошибка связана с функцией Min
. Он выдает исключение, если источник не содержит элементов. Ниже приводится краткое описание функции Min
:
//
// Summary:
// Returns the minimum value in a sequence of System.Int32 values.
//
// Parameters:
// source:
// A sequence of System.Int32 values to determine the minimum value of.
//
// Returns:
// The minimum value in the sequence.
//
// Exceptions:
// T:System.ArgumentNullException:
// source is null.
//
// T:System.InvalidOperationException:
// source contains no elements.
[__DynamicallyInvokable]
public static int Min(this IEnumerable<int> source)
Если во всех строках столбца reason
есть данные, ваша функция Where
вернет пустое перечислимое. Это потому, что IsNullOrEmpty — ваше первое условие. А поскольку вы используете операцию &&
, выражение всегда будет иметь значение false, если столбец причины не равен нулю или не пуст.
Вы можете решить эту проблему, используя DefaultIfEmpty
, как объяснил Кристофер Летте в этом ответе Stackoverflow https://stackoverflow.com/a/2167461/24889207. Для ссылочных типов в C# значение по умолчанию — null
. Итак, вам, возможно, придется с этим справиться.
Кстати, вы можете напрямую вернуть результат Min
вместо того, чтобы заключать его в условие if и возвращать true.
Пример:
return StudentDetails.rows
.Where(c => string.IsNullOrEmpty(c.reason) && !c.leave)
.DefaultIfEmpty()
.Min(c => c?.joiningdate ?? DateTime.UtcNow) < DateTime.UtcNow.AddDays(-180)
Min
выдает исключение, если элементов нет, но только если T
является типом значения, не допускающим значения NULL. Таким образом, вы можете просто привести к нулю.
if (StudentDetails.rows
.Where(c => !c.leave && string.IsNullOrEmpty(c.reason))
.Min(c => (DateTime?) c.joiningdate) < DateTime.UtcNow.AddDays(-180))
return true;
Подразумевается, что нет строк, в которых «разум» имеет значение null, а «leaveL» — ложь. Как вы думаете, они есть?