Search code examples
c#entity-frameworkcsvhelper

CsvHelper : Intialize a map member


Imagine a collection of EF dbSet like this :

public class Employee {
  ...
  public string FirstName { get; set; }
  public List<Badge> Badge { get; set; } 
}

public class Badge {
  public long CSN { get; set; }
  public int EmployeeId { get; set; }
  public int Type { get; set; }
}

This models are used in my SGBB and I want to use it to import data from a CSV file. But this file has a small difference. It give only one badge like this :

FIRSTNAME;CSN;TYPE
Jerome;12345;1

I have used a CollectionGenericConverter, to initialize the List with a new record.

Map(m => m.Firstname).Name("Firstname");
Map(m => m.Badges).Name("CSN").TypeConverter<BadgeConverter>();

...

public class BadgeConverter : CollectionGenericConverter {
   public override object ConvertFromString(String text, IReaderRow row, MemberMapData memberMapData) {
       return new List<Badge> {
           new Badge {
               CSN = Convert.ToInt16(text)
           }
       };
   }
}

I have just a problem with the second value, using a second converter reset the list of badges :

 Map(m => m.Badges).Name("Type").TypeConverter<AnotherOneBadgeConverter>();

And set directly the first item not work :

 Map(m => m.Badges[0].Type).Name("Type");

How to do that ?


Solution

  • Something like this may work for you.

    public class Program
    {
        public static void Main(string[] args)
        {
            using (MemoryStream stream = new MemoryStream())
            using (StreamWriter writer = new StreamWriter(stream))
            using (StreamReader reader = new StreamReader(stream))
            using (CsvReader csv = new CsvReader(reader))
            {
                writer.WriteLine("FIRSTNAME;CSN;TYPE");
                writer.WriteLine("Jerome;12345;1");
                writer.Flush();
                stream.Position = 0;
    
                csv.Configuration.Delimiter = ";";
                csv.Configuration.RegisterClassMap<EmployeeMap>();
    
                var records = csv.GetRecords<Employee>().ToList();
            }
        }
    }
    
    public class Employee
    {  
        public string FirstName { get; set; }
        public List<Badge> Badge { get; set; }
    }
    
    public class Badge
    {
        public long CSN { get; set; }
        public int EmployeeId { get; set; }
        public int Type { get; set; }
    }
    
    public class EmployeeMap: ClassMap<Employee>
    {
        public EmployeeMap()
        {
            Map(m => m.FirstName).Name("FIRSTNAME");
            Map(m => m.Badge).ConvertUsing(row =>
            {
                var list = new List<Badge>
                {
                    new Badge { CSN = row.GetField<long>("CSN"), Type = row.GetField<int>("TYPE") },
                };
                return list;
            });
        }
    }