Gautam G
Gautam G

Reputation: 494

How to handle null values in linq?

recordsList.ListOfRecords = new StudentRecordsBAL()
                                .GetStudentsList()
                                .Select(q => new StudentRecords()
            {
                _RollNumber = q._RollNumber,
                _Class = q._Class,
                _Name = q._Name,
                _Address = q._Address,
                _City = q._City,
                _State = q._State,
                _Subjects = q._Subject,
                _AttendedDays = new AttendanceBAL()
                                    .GetAttendanceListOf(q._RollNumber)
                                    .Where(date => date != null)
                                    .Select(date => 
                                        new DateTime(date._Date.Year, date._Date.Month, date._Date.Day))
                                    .Distinct()
                                    .ToList(),
                _AttendedSubjects = GetAttendedSubjects(q._RollNumber)                                            
        }).ToList(); 

The method, GetAttendanceListOf(q._RollNumber) in above code will return a list of records from the database or "null" if there are no records present for the passed "roll-no". A linq query will be terminated generating error

"Value cannot be null".

Is there a way to handle this error and make LINQ jump to next step?

Upvotes: 8

Views: 58588

Answers (5)

Mat J
Mat J

Reputation: 5632

For a quick fix, Modify this line

_AttendedDays = new AttendanceBAL().GetAttendanceListOf(q._RollNumber).Where...

To this

_AttendedDays = (new AttendanceBAL().GetAttendanceListOf(q._RollNumber)??new List()).Where...

Upvotes: 0

Eli Algranti
Eli Algranti

Reputation: 9007

As suggested by @Zdeslav Vojkovic modify GetAttendanceListOf to return empty list if null or do something like:

_AttendedDays = (new AttendanceBAL()
    .GetAttendanceListOf(q._RollNumber) ?? Enumerator.Empty<typeofrecord>())
    .Where(date => date != null)
    .Select(date => new DateTime(date._Date.Year, date._Date.Month, date._Date.Day))
    .Distinct()
    .ToList(),

(you might be able to do it without the extra parenthesis)

Upvotes: 0

Zdeslav Vojkovic
Zdeslav Vojkovic

Reputation: 14591

_AttendedDays = new AttendanceBAL()
    .GetAttendanceListOf(q._RollNumber)
    .Where(date => date != null)
    .Select(date => new DateTime(date._Date.Year, date._Date.Month, date._Date.Day))
    .Distinct()
    .ToList(),

The problem is with running Where() on null instance. Possible solutions:

1) modify GetAttendanceListOf to return an empty list if no attendance (good idea in general, as null object pattern is very often a life saver, and for collection, an empty collection is often semantically similar to null)
2) if you don't control that method, write a safe extension method which will return empty list in case of null, e.g.

List<AttendanceType> SafeAttendanceList(this AttendanceBALType bal, RollNumber rn)
{
    return bal.GetAttendanceListOf(rn) ?? new List<AttendanceType>();
}

Then call it as:

_AttendedDays = new AttendanceBAL()
    .SafeAttendanceListOf(q._RollNumber)
    .Where(date => date != null)

Upvotes: 11

Noone
Noone

Reputation: 425

Linq ToList() will return an empty list if there are no results. The error might comes from elsewhere.

I would recommand you to use methods to create your objects, it will make your query easier to read and to debug. I would recommand that you do it in multiple steps to determine what is getting null and where exactly it fails to execute.

The error might comes from GetAttendanceListOf(), when having methods returning IList or IEnumerable, you should return an empty list if there is no results, it will prevent you from validating every time if it's null or not.

Upvotes: 0

Cornelius
Cornelius

Reputation: 3616

You can try

recordsList.ListOfRecords = new StudentRecordsBAL().GetStudentsList().Select(q => 
            {
                var attendanceList = new AttendanceBAL().GetAttendanceListOf(q._RollNumber);
                if (attendanceList == null)
                    return null;
                return new StudentRecords()
                    {
                        _RollNumber = q._RollNumber,
                        _Class = q._Class,
                        _Name = q._Name,
                        _Address = q._Address,
                        _City = q._City,
                        _State = q._State,
                        _Subjects = q._Subject,
                        _AttendedDays = attendanceList.Where(date => date != null).Select(date => new DateTime(date._Date.Year, date._Date.Month, date._Date.Day)).Distinct().ToList(),
                        _AttendedSubjects = GetAttendedSubjects(q._RollNumber)
                    };
            }).Where(q => q != null).ToList(); 

This checks that you do not do a Where operation on a null object and filter out any null results.

Upvotes: 0

Related Questions