Попытка разбить строки CSV на несколько классов с помощью CsvHelper - PullRequest
0 голосов
/ 17 мая 2019

У меня есть CSV с одной строкой заголовка. Некоторые столбцы каждой строки должны отображаться на один класс, тогда как другие столбцы строки должны отображаться на другой класс.

Я пробовал это, но безуспешно:

using(var reader = new StreamReader(@"c:\temp\myfile.csv"))
{
    using(var csv = new CsvReader(reader))
    {
       csv.Configuration.RegisterClassMap<ClientMap>();
       csv.Configuration.RegisterClassMap<BookingMap>();

       var bookings = csv.GetRecords<Booking>();
       ... //iterate over bookings and write to Console

       reader.BaseStream.Position = 0;

       var clients = csv.GetRecords<Client>();
       ... //iterate over clients and write to Console
    }
}

Классы

public class Client {
   public string Firstname {get; set;}
   public string Lastname {get; set;}
   public AgesEnum Age {get; set;}
}

public class Booking {
    public string ExternalId {get; set;}
    public string Status {get; set;}
}

Карты

public class ClientMap : ClassMap<Client> 
{
   public ClientMap()
   {
       Map(m => m.Firstname).Name("FIRSTNAM");
       Map(m => m.Lastname).Name("LASTNAME");
       Map(m => m.Age).ConvertUsing(row =>{
          var age = row.GetField<int>("AGE");

          if(age < 2)
             return AgesEnum.Baby;
          if(age < 10)
             return AgesEnum.Young;
          if(age < 40)
             return AgesEnum.Middle;
          return AgesEnum.Old;
       } );
    }
}


public BookingMap : ClassMap<Booking>
{
    public BookingMap()
    {
        Map(b => b.ExternalId).Name("SYSID");
        Map(b => b.Status);
    }
}

Что происходит, когда я запускаю, это то, что bookings возвращаются нормально, и я могу перебирать их. Однако в строке GetRecords<Client>() появляется сообщение о том, что

Преобразование не может быть выполнено. Текст: 'Age' MemberType: TypeConverter: 'CsvHelper.TypeConversion.Int32Converter'

Если я закомментирую весь код, относящийся к бронированию, и выполню только GetRecords<Client>(), я не получу ошибку.

Почему это не сработает? Должен ли я установить совершенно новый StreamReader?

Ответы [ 2 ]

0 голосов
/ 17 мая 2019

Проблема в том, что вы устанавливаете позицию потока обратно в начало, а CsvReader думает, что вы уже прочитали заголовок, когда получили заказы, поэтому он снова читает первую строку как данные, а не как заголовок. Вам нужно снова прочитать заголовок вручную.

using(var reader = new StreamReader(@"c:\temp\myfile.csv"))
{
    using(var csv = new CsvReader(reader))
    {
       csv.Configuration.RegisterClassMap<ClientMap>();
       csv.Configuration.RegisterClassMap<BookingMap>();

       var bookings = csv.GetRecords<Booking>();
       ... //iterate over bookings and write to Console

       reader.BaseStream.Position = 0;

       csv.Read();
       csv.ReadHeader();

       var clients = csv.GetRecords<Client>();
       ... //iterate over clients and write to Console
    }
}
0 голосов
/ 17 мая 2019

Я думаю, вы можете найти что-то интересное относительно использования Enums с CsvHelper прямо здесь

...