Question

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?

Was it helpful?

Solution

_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)

OTHER TIPS

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.

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.

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)

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...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top