Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CsvHelper: No members are mapped for type

Tags:

c#

csvhelper

I use CsvHelper 4.0.3.

I have a nested class defined like this:

private class CsvLine {
    public string Solution;
    public string Project;
    public string DependsOnProject;
    public string Weight;
    public string DependsOnPackage;
    public string PackageVersion;
}

My .csv file, which I want to parse using CsvHelper, has these field names:

Solution,Project,DependsOnProject,Weight,DependsOnPackage,PackageVersion

Here is my code:

TextReader readFile = new StreamReader(dependenciesCsvFilePath);
var csvReader = new CsvReader(readFile);
IEnumerable<CsvLine> records = csvReader.GetRecords<CsvLine>();

According to the documentation here, the code above should work.

However, when I inspect records, I see the message No members are mapped for type 'ParentClass+CsvLine'.

I changed the accessibility of CsvLine from private to public, but that made no difference.

What did I do wrong?

EDIT: I have tried un-nesting the CsvLine class and making it public, but that did not help either.

EDIT: I made the changes as Nkosi suggested; however, now it says that records is an empty collection: "Enumeration yielded no results". There are definitely data present inside my .csv file, so the collection shouldn't be empty.

Here are some sample data:

Solution,Project,DependsOnProject,Weight,DependsOnPackage,PackageVersion
FOD.sln,ABC.DEF,IMS.ABC,1,,
FOD.sln,ABC.DEF,IMS.DEF,1,,
FOD.sln,ABC.DEF,IMS.GHI,1,,
FOD.sln,ABC.DEF,IMS.JKL,1,,

EDIT: Solved! Nkosi's and Panagiotis' answers complement each other's.

like image 913
M.Y. Babt Avatar asked Nov 01 '17 15:11

M.Y. Babt


4 Answers

As of CsvHelper 12.2.2, this is what I've had to do to get it to work

csv.Read() 
csv.ReadHeader()
csv.GetRecords<T>().ToList();

For some reason despite CsvReader's documentation, adding the Read() and ReadHeader() methods will get it to actually pull in the data from the csv file.

like image 98
kyle_l Avatar answered Sep 23 '22 11:09

kyle_l


You need to use Properties instead of fields in the object model as by default, it will map the matching public members

public class CsvLine {
    public string Solution { get; set; }
    public string Project { get; set; }
    public string DependsOnProject { get; set; }
    public string Weight { get; set; }
    public string DependsOnPackage { get; set; }
    public string PackageVersion { get; set; }
}

You should also read up on mapping your classes to the csv file.

CsvHelper: Class Mapping

like image 22
Nkosi Avatar answered Oct 13 '22 22:10

Nkosi


Nkosi explained that CsvHelper maps to properties by default.

I've encountered the Enumeration yielded no results message in the debugger in the past. The message is misleading. There are records even though the debugger says there aren't. You iterate over the IEnumerable with foreach or call .ToArray() or .ToList() on it to load all records, eg:

var records = csvReader.GetRecords<CsvLine>();
foreach(var record in records)
{
     ...
}

Or

var records = csvReader.GetRecords<CsvLine>().ToArray();

You can force the debugger to show all items in an IEnumerable in the Watch, Quick Watch or Immediate window by adding the results format specifier, eg:

records,results

Be careful because this will execute the IEnumerable and return all results.

You can find this, and other tricks in 7 Hidden Gems in Visual Studio 2017

like image 9
Panagiotis Kanavos Avatar answered Oct 13 '22 22:10

Panagiotis Kanavos


Other possible causes:

  • Header string quote char.
  • delimiter char.

Example code to config them:

var conf = new CsvHelper.Configuration.Configuration();
conf.Delimiter = ",";
conf.Quote = '\'';
var csv = new CsvHelper.CsvReader(reader, conf);
var rows = csv.GetReads<MyClass>();
like image 3
Robin Qiu Avatar answered Oct 14 '22 00:10

Robin Qiu