C# CsvHelper:WriteRecord 抛出“ConfigurationException:不能自动映射继承 IEnumerable 的类型”
Posted
技术标签:
【中文标题】C# CsvHelper:WriteRecord 抛出“ConfigurationException:不能自动映射继承 IEnumerable 的类型”【英文标题】:C# CsvHelper: WriteRecord throws "ConfigurationException: Types that inherit IEnumerable cannot be auto mapped" 【发布时间】:2021-11-28 04:30:42 【问题描述】:这是我的原始代码,在没有 CsvHelper 的情况下写入 CSV 文件。
public static void Write(string file, List<PayRecord> payrecords)
using(StreamWriter sw = new StreamWriter(file))
sw.WriteLine("EmployeeId,Gross,Tax,Net");
foreach(PayRecord c in payrecords)
string line = string.Format("0,1,2,3",
c.Id,
c.Gross,
c.Tax,
c.Net);
sw.WriteLine(line);
这是相同的代码,但这次使用的是 CsvHelper:
public static void Write(string file, List<PayRecord> payrecords)
using (StreamWriter sw = new StreamWriter(file))
using (CsvWriter cw = new CsvWriter(sw, CultureInfo.CurrentCulture))
cw.WriteHeader<PayRecord>();
foreach (var c in payrecords)
string line = string.Format("0,1,2,3",
c.Id,
c.Gross,
c.Tax,
c.Net);
cw.WriteRecord(line);
但我遇到了以下异常:
Unhandled exception. CsvHelper.Configuration.ConfigurationException: Types that inherit IEnumerable cannot be auto mapped. Did you accidentally call GetRecord or WriteRecord which acts on a single record instead of calling GetRecords or WriteRecords which acts on a list of records?
at CsvHelper.CsvWriter.WriteRecord[T](T record)
和:
Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'source')
at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
at CsvHelper.Configuration.ClassMap.AutoMapConstructorParameters(ClassMap map, CsvContext context, LinkedList`1 mapParents, Int32 indexStart)
at CsvHelper.Configuration.ClassMap.AutoMapConstructorParameters(ClassMap map, CsvContext context, LinkedList`1 mapParents, Int32 indexStart)
at CsvHelper.Configuration.ClassMap.AutoMap(CsvContext context)
at CsvHelper.CsvContext.AutoMap(Type type)
at CsvHelper.CsvWriter.WriteHeader(Type type)
at CsvHelper.CsvWriter.WriteHeader[T]()
怎么了?
【问题讨论】:
你也可以分享你的PayRecord
课程吗?
您不应该将字符串写入 csv 文件,不确定通过在此处切换到 CsvHelper 获得了什么,因为您似乎仍在自己完成所有工作。相反,您应该编写实际的对象。
【参考方案1】:
您正在尝试写一个string
作为记录。
cw.WriteRecord(line);
我无法重现您的 ArgumentNullException
,但我知道即使修复了该问题,您的代码仍然无法正常工作。
上面将抛出 CsvHelper.Configuration.ConfigurationException
,因为 string
被归类为单个字段,CsvHelper.WriteRecord
更多地用于类而不是 string
。
其次,CsvWriter.WriteHeader
不会将“光标”移动到下一行,因此您需要使用CsvWriter.NextRecord()
,否则您的数据将与标题在同一行。
以下代码有效:
public static void Write(string file, List<PayRecord> payrecords)
using(StreamWriter sw = new StreamWriter(file))
using(CsvWriter cw = new CsvWriter(sw, CultureInfo.CurrentCulture))
cw.WriteHeader<PayRecord>();
cw.NextRecord();
foreach(var c in payrecords)
cw.WriteRecord(line);
但是,最好不要手动编写标题,使用CsvHelper.WriteRecords
并传递整个对象集合,如下所示。
这导致正确使用CsvHelper.WriteRecords
的代码更小、更简洁、更高效,同时还编写了正确的标头。
这更好:
public static void Write(string file, List<PayRecord> payrecords)
using (StreamWriter sw = new StreamWriter(file))
using (CsvWriter cw = new CsvWriter(sw, CultureInfo.CurrentCulture))
cw.WriteRecords(payrecords);
更好?
要在不阻塞主线程的情况下执行 I/O 操作(写入 CSV 文件),请使用 CsvHelper.WriteRecordsAsync
,使用 await using
不阻塞资源清理并让您的方法 async
能够@987654337 @电话。
我也会使用ICollection<PayRecord>
,这样如果您将List<PayRecord>
更改为实现ICollection
的任何其他类型,您就不需要更改方法。
鲜奶油:
public static async Task WritePayRecords(string file, ICollection<PayRecord> payrecords)
await using (StreamWriter sw = new StreamWriter(file))
await using (CsvWriter cw = new CsvWriter(sw, CultureInfo.CurrentCulture))
if (payrecords == null)
throw new ArgumentNullException(nameof(payrecords), "Collection of pay records cannot be null");
await cw.WriteRecordsAsync(payrecords);
上面的代码甚至可以使用null
字段、null
对象,并且如果集合是null
也会抛出异常(否则,CsvHelper 将抛出异常)。
希望有帮助!
【讨论】:
以上是关于C# CsvHelper:WriteRecord 抛出“ConfigurationException:不能自动映射继承 IEnumerable 的类型”的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 中使用 csvHelper 将两个单独列中的日期和时间合并到一个新的日期时间列中
使用 CSVhelper 将单个列更新为先前编写的 CSV 文件。我有 Java 代码,但无法将其翻译成 C#
C#导出csv文件,不依赖System.Drawing.Common导出excel文件,导致在docker使用失败。CsvHelper支持跨平台使用