Rob
Rob

Reputation: 199

Populating a View Model with a foreach loop when one field could be null?

I have some old tables from an old database which I am trying to use to populate a View Model. The controller action looks for records in one old table where the email matches the current users email and then populates the View Model based on a list derived from those matches. This is my controller action:

public PartialViewResult OldCourses()
    {
        var email = User.Identity.GetEmail();

        var reglist = nb.old_register
            .Where(i => i.email == email).ToList();

        if (reglist != null)
        {
            var viewModel = new OldCourseViewModel();

            foreach (var reg in reglist)
            {
                viewModel.StudentID = reg.studentid;
                viewModel.CourseTitle = nb.old_courses.FirstOrDefault(j => j.courseid == nb.old_Cohorts.FirstOrDefault(h => h.cohortname == reg.cohort).modulename).coursetitle;
                viewModel.Cohort = reg.cohort;
                viewModel.Progpct = nb.student_progress.FirstOrDefault(k => k.studentid == reg.studentid).percentage;
            };


            return PartialView("OldCourses", viewModel);
        }

It is possible for viewModel.Progpct to return null as there may not be an entry in the student_progress table for each record in reglist. This means I get an error, Object reference not set to an instance of an object.

The View Model is as follows:

public class OldCourseViewModel
{
    public int StudentID { get; set; }
    public string CourseTitle { get; set; }
    public string Cohort { get; set; }
    public decimal? Progpct { get; set; }
    public string icon_class { get; set; }
    public string icon_colour_class { get; set; }
    public string titleabbrev { get; set; }

}

The field 'percentage' from the old table is as follows:

public Nullable<decimal> percentage { get; set; }

None of the old tables have foreign key relationships and I can't change any of those tables in any way.

I appreciate that the foreach loop can't handle the null, even though the field is nullable in the View Model.

My first question is what is the best way to handle this situation so that this field can be returned null when it is null?

My second question is, if there are multiple records in the reglist, how can I make the foreach loop cycle through each record in the reglist and generate a new record in the View Model for each of those in the reglist?

Edit - On Stephen's suggestion, I did the following:

var pctcheck = nb.student_progress.FirstOrDefault(k => k.studentid == reg.studentid);

                if (pctcheck != null)
                {
                    viewModel.Progpct = pctcheck.percentage;
                }          

This answers my first question correctly. Stephen also answered my second question correctly in the comments.

The accepted answer is the best way of completing my first question, rather than the above I used:

viewModel.Progpct = nb.student_progress.FirstOrDefault(k => k.studentid == reg.studentid)?.percentage;

Which uses the ?. operator to do the same job as the if null check.

Upvotes: 1

Views: 1665

Answers (1)

Rapha&#235;l Althaus
Rapha&#235;l Althaus

Reputation: 60493

For the first question, even if you fixed it, you may use, in new versions of c#, the ?. operator

viewModel.Progpct = nb.student_progress.FirstOrDefault(k => k.studentid == reg.studentid)?.percentage;

in older versions, you may use

viewModel.Progpct = nb.student_progress.Where(k => k.studentid == reg.studentid).Select(m => (decimal?)m.percentage).FirstOrDefault();

for the second question, you could simplify with something like that.

Your model will be an IEnumerable<OldCourseViewModel>

var email = User.Identity.GetEmail();

var model = nb.old_register.Where(i => i.email == email)
     .Select(reg => new OldCourseViewModel {

           StudentID = reg.studentid,
           CourseTitle = nb.old_courses.FirstOrDefault(j => j.courseid == nb.old_Cohorts.FirstOrDefault(h => h.cohortname == reg.cohort)?.modulename)?.coursetitle;
           Cohort = reg.cohort,
           Progpct = nb.student_progress.FirstOrDefault(k => k.studentid == reg.studentid)?.percentage
       });

return PartialView("OldCourses", model);

Upvotes: 2

Related Questions