CSVHelper无法映射结果

问题描述 投票:-1回答:1

我有一个文件导入,允许用户导入CSV文件,该文件允许程序将数据添加到数据库。由于CSV文件的大小取决于要添加的数据,因此存在多个映射文件,这就是为什么有多个映射类都从CSVBooking继承的原因

List<string> headers = SplitCSV(textReader.ReadLine()).ToList();
//Called again to reset pos
textReader = new StreamReader(importBookingsFilePath.Text);
var records = new List<CSVBooking>();
using (var reader = new StringReader(textReader.ReadToEnd()))
{
     var parser = new CsvParser(reader, CultureInfo.InvariantCulture);
     if (parser.Read() != null)
         using (var csv = new CsvReader(parser))
         {
             switch (headers.Count)
             {
                  case 77:
                  case 86:
                      csv.Configuration.RegisterClassMap<CSVBookingMapNonPayment>();
                      break;
                  case 78:
                  case 91:
                       csv.Configuration.RegisterClassMap<CSVBookingMapPayment>();
                       break;
                  case 79 when headers.Contains("IP") || headers.Contains("\"IP\""):
                       csv.Configuration.RegisterClassMap<CSVBookingMapNonPaymentExtraIPInfo>();
                       break;
                  case 74:
                       csv.Configuration.RegisterClassMap<CSVBookingMapNonPayment_DaySail>();
                       break;
                  case 87:
                       csv.Configuration.RegisterClassMap<CSVBookingMapNonPayment_Group>();
                       break;
                  case 93:
                       csv.Configuration.RegisterClassMap<CSVBookingMap_Payment_Crew>();
                       break;
                   default:
                       csv.Configuration.HeaderValidated = null;
                       csv.Configuration.AutoMap<CSVBooking>();
                       break;
              }
              records = csv.GetRecords<CSVBooking>().ToList();
        }
        else
        {
               MessageBox.Show($"There was an error parsing the file:\n{importBookingsFilePath.Text}", "Parsing error", MessageBoxButton.OK, MessageBoxImage.Error);
               return;
         }

switch语句在案例87中运行,提供了我提供的文件,parser.Read()返回有效的标头和数据。

此程序当前使用的映射文件:

class CSVBookingMapNonPayment_Group: ClassMap<CSVBooking>
{
     public CSVBookingMap_Payment_Crew()
     {
          Map(m => m.SubmissionDateTime).Index(0);
          Map(m => m.Title).Index(1);
          Map(m => m.Surname).Index(2);
          Map(m => m.Firstname).Index(3);
          Map(m => m.AKA).Index(4);
          ...
    }
}

class CSVBooking
{
    public string IP { get; set; }
    public string SubmissionID { get; set; }
    [Index(0)]
    public string SubmissionDateTime { get; set; }
    [Index(1)]
    public string Title { get; set; }
    [Index(2)]
    public string Surname { get; set; }
    [Index(3)]
    public string Firstname { get; set; }
    ...
}
c# csvhelper
1个回答
1
投票

您正在从TextReader中读取一行,然后将同一TextReader传递到CsvReader中。这意味着CsvReader将开始读取TextReader所在的位置,这是第二行。它会将第一行视为标题行,并将其与注册的地图匹配。在您的情况下,那是一个数据行,而不是标题。

我的建议是立即注册所有地图。每当调用GetRecord<MyType>时,它将使用该类型的注册映射。您可以根据需要在一行上读取几种类型,或者每行读取另一种类型。

[在CsvHelper中执行操作的方式如下所示。

void Main()
{
    var s = new StringBuilder();
    s.AppendLine("Id,Name");
    s.AppendLine("1,one");
    s.AppendLine("2,two");
    using (var reader = new StringReader(s.ToString()))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        csv.Read();
        csv.ReadHeader();

        if (csv.Context.HeaderRecord.Length == 2)
        {
            csv.Configuration.RegisterClassMap<FooMap>();
        }
        else if (csv.Context.HeaderRecord.Length == 3)
        {
            csv.Configuration.RegisterClassMap<BarMap>();
        }

        csv.GetRecords<Foo>().ToList().Dump();
    }
}

public class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Bar
{
    public Guid Property1 { get; set; }
    public decimal Cost { get; set; }
    public DateTimeOffset Date { get; set; }
}

public class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
    }
}

public class BarMap : ClassMap<Bar>
{
    public BarMap()
    {
        Map(m => m.Property1);
        Map(m => m.Cost);
        Map(m => m.Date);
    }
}

同样,我建议仅注册所有地图,而不使用if语句。

您想使用CsvHelper阅读第一行的另一个原因是,字段中可能会有换行符。如果发生这种情况,通过TextReader读取一行将无法获得完整的CSV行。

© www.soinside.com 2019 - 2024. All rights reserved.