CsvHelper:没有为该类型映射任何成员。

15

我使用CsvHelper 4.0.3

我定义了一个嵌套的类,如下所示:

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

我想使用 CsvHelper 解析我的 .csv 文件,它包含以下字段:

Solution,Project,DependsOnProject,Weight,DependsOnPackage,PackageVersion

这是我的代码:

TextReader readFile = new StreamReader(dependenciesCsvFilePath);
var csvReader = new CsvReader(readFile);
IEnumerable<CsvLine> records = csvReader.GetRecords<CsvLine>();
根据这里的文档,上面的代码应该可以工作。

然而,当我检查records时,我看到消息No members are mapped for type 'ParentClass+CsvLine'

我将CsvLine的可访问性从private更改为public,但没有任何变化。

我做错了什么?

编辑:我尝试取消嵌套CsvLine类并使其公开,但那也没有帮助。

编辑:我按照Nkosi建议进行了更改;然而,现在它说records是一个空集合:“Enumeration yielded no results”。我的.csv文件中肯定有数据存在,所以集合不应该是空的。

这里有一些样本数据:

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

编辑:问题已解决!NkosiPanagiotis的答案互相补充。


文件中的头在哪里?如果没有头,则必须创建一个类映射以通过索引进行映射。 - Nkosi
2
使用.GetRecords<CsvLine>().ToArray()先加载数据,然后检查它们。我曾经看到调试器抱怨空枚举,即使有记录。顺便问一下,你使用的是哪个版本的CsvHelper?它几乎每周都会更改版本。 - Panagiotis Kanavos
1
@PanagiotisKanavos 调用ToArray()方法解决了问题。谢谢! - M.Y. Babt
@MY_G 检查一下它是否也适用于字段(应该是的)。如果是的话,那么我应该删除我的答案,因为它将不再适用。 - Nkosi
@MY_G,你可以在观察窗口中添加,results格式说明符,强制调试器评估IEnumerable并返回所有结果,例如 record,results。但请确保不要在大文件上使用此功能。 - Panagiotis Kanavos
显示剩余5条评论
5个回答

27

默认情况下,对象模型将映射匹配的公共成员,因此您需要使用属性而不是字段。

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; }
}

你还应该了解如何将你的类映射到csv文件中。

CsvHelper: 类型映射


谢谢您的回复!我按照您的建议进行了更改;然而,现在它显示“records”是一个空集合:“枚举未产生结果”。我的.csv文件中肯定有数据存在,所以集合不应该为空。 - M.Y. Babt
4
我曾经和 @my_g 一样出现了相同的症状,通过将所有属性的私有设置器更改为公共设置器解决了这个问题。 - Anders Juul
请注意@robin-qiu的答案 - leguminator

11

Nkosi解释说,CsvHelper默认将映射到属性。

我以前在调试器中遇到过“枚举未产生结果”的消息。这个消息是误导性的。虽然调试器说没有记录,但实际上是有的。您可以使用foreach迭代IEnumerable,或者调用.ToArray().ToList()来加载所有记录,例如:

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

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

您可以通过添加results格式说明符,来强制调试器在观察、快速观察或立即窗口中显示IEnumerable中的所有项,例如:

records,results

注意,这将执行IEnumerable并返回所有结果。

您可以在《Visual Studio 2017中的7个隐藏珠宝》中找到此功能和其他技巧。


谢谢!我试图在QuickWatch中查看结果对象,但它显示“枚举未产生结果”。添加foreach后,我可以检查每个记录。谢谢!var records = csv.GetRecords<dynamic>(); foreach(var record in records) { string recordObject = JsonConvert.SerializeObject(record); } - Michael Herchenroder

5

问题有一个更简单的解决方案,只需要一行代码。您需要告诉csvhelper查看您的字段。

using (var csv = new CsvWriter(writer))
{
    csv.Configuration.MemberTypes = CsvHelper.Configuration.MemberTypes.Fields;
.....
}

MemberTypes现在是只读的。 - mugi

4

其他可能的原因:

  • 标题字符串引用字符。
  • 分隔符字符。

配置它们的示例代码:

var conf = new CsvHelper.Configuration.Configuration();
conf.Delimiter = ",";
conf.Quote = '\'';
var csv = new CsvHelper.CsvReader(reader, conf);
var rows = csv.GetReads<MyClass>();

我遇到了相同的问题,即使添加了ClassMap也是如此。分隔符也与此有关! - leguminator

1
截至CsvHelper 12.2.2版本,以下是我所做的使其正常工作的步骤。
csv.Read() 
csv.ReadHeader()
csv.GetRecords<T>().ToList();

由于某些原因,尽管CsvReader文档中没有提到,但添加Read()和ReadHeader()方法将使其实际从csv文件中获取数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接