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&lt;PayRecord&gt;,这样如果您将List&lt;PayRecord&gt; 更改为实现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 无法使用自定义映射编写

如何在 C# 中使用 csvHelper 将两个单独列中的日期和时间合并到一个新的日期时间列中

使用 CSVhelper 将单个列更新为先前编写的 CSV 文件。我有 Java 代码,但无法将其翻译成 C#

C#导出csv文件,不依赖System.Drawing.Common导出excel文件,导致在docker使用失败。CsvHelper支持跨平台使用

使用 CsvHelper 读取多头 CSV 文件

如何使用 csvhelper 将数据插入位列?