Error exporting to CSV when there are reference maps

170 views Asked by At

I have s Student class where each student record has a list of Results. I need to export there results to CSV and I'm using CsvHelper.

public class Student
{
   public string Id { get; set; }
   public string Name { get; set; }
   public Result[] Grades { get; set; }
}

public class Result
{
   public string Subject { get; set; }
   public decimal? Marks { get; set; }
}

I'm using Reference Maps to map the list of Results, but when exporting to CSV it throws and error.

Mapping Code

public sealed class StudentResultExportMap : ClassMap<Student>
{
    public StudentResultExportMap ()
    {
        AutoMap();
        References<GradesMap>(m => m.Grades);
    }
}

public sealed class GradesMap: ClassMap<Result>
{
    public GradesMap()
    {
        Map(m => m.Subject);
        Map(m => m.Marks);
    }
}

Error

Property 'System.String Subject' is not defined for type '{namespace}.GetStudentResults+Result[]' Parameter name: property

1

There are 1 answers

0
David Specht On

Unfortunately References<GradesMap>(m => m.Grades); doesn't work for an array of Result. It would work for an individual result. I have one solution, which overrides the ToString() method of Result to flatten the grades. It might work for you, depending on what you need.

public class Result
{
    public string Subject { get; set; }
    public decimal? Marks { get; set; }
    public override string ToString()
    {
        return $"{Subject} = {Marks}";
    }
}

Make a slight change to your StudentResultExportMap. You can set the 2nd number on .Index(2, 7) to handle the max number of grades you think a student might have.

public sealed class StudentResultExportMap : ClassMap<Student>
{
    public StudentResultExportMap()
    {
        AutoMap();
        Map(m => m.Grades).Name("Grade").Index(2, 7);
    }
}

You will then get Id, Name, Grade1, Grade2, Grade3, Grade4, Grade5, Grade6 with the toString() value of Result for each grade.

var records = new List<Student>
{
    new Student{ Id = "1", Name = "First", Grades =  new [] {
        new Result { Subject = "Subject1", Marks = (decimal)2.5 } ,
        new Result { Subject = "Subject2", Marks = (decimal)3.5 } }},
    new Student{ Id = "2", Name = "Second", Grades =  new [] {
        new Result { Subject = "Subject1", Marks = (decimal)3.5 } ,
        new Result { Subject = "Subject2", Marks = (decimal)4.0 } }}
};

using (var writer = new StreamWriter("path\\to\\StudentResults.csv"))
using (var csv = new CsvWriter(writer))
{
    csv.Configuration.RegisterClassMap<StudentResultExportMap>();
    csv.WriteRecords(records);
}