c# - C# CsvHelper:WriteRecord 抛出“ConfigurationException:不能自动映射继承 IEnumerable 的类型”
问题描述
这是我的原始代码,在没有 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]()
怎么了?
解决方案
您正在尝试将 a 写string
为记录。
cw.WriteRecord(line);
我无法重现您的ArgumentNullException
内容,但我知道即使修复了该问题,您的代码仍然无法正常工作。
上面将抛出 a CsvHelper.Configuration.ConfigurationException
,因为 astring
被归类为单个字段,CsvHelper.WriteRecord
并且更多的是用于类而不是 a 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
, useawait using
来不阻塞资源清理并使您的方法async
能够await
调用。
我也会使用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 将抛出异常)。
希望有帮助!
推荐阅读
- active-directory - 使用 Active Directory 验证 rails 6 应用程序
- python - 如何使用python查找数据框中的空格数
- qt - Qt 错误:QFontEngineFT:无法创建 FreeType 字体引擎
- javascript - 防止 mouseup 上的 click 事件和 Click 上的 mouseup 事件
- recaptcha - 为什么谷歌recaptcha.execute返回null?
- reactjs - React Material UI 表格排序
- python - 如何使用python中的键盘模块模拟向上键?
- python - Download fails with "Authentication failed" when we try to download 50+ files from SFTP serially using pysftp in Python?
- windows - 如何在整个文件夹结构中使用包含特定字符串的批处理脚本查找文件?
- mvvm - 在没有 Cesium.knockout 的情况下更改 cesium 模型的属性时如何实时更新视图