Reputation: 53
I'm trying to write a complex object (contains lists) as a flat object.
public class PersonDTO
{
public Guid Id { get; set; }
public PersonDetails details { get; set; }
public List<Book> Books { get; set; }
}
public class PersonDetails
{
public string FName { get; set; }
public string LName { get; set; }
}
public class Book
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<Page> Pages { get; set; }
}
public class Page
{
public Guid Id { get; set; }
}
The number of csv records should be the number of the inner collection length.
For example, PersonDTO has list of books, book has list of pages. I'd like to get the following csv:
personId | FName | LName | BookId | BookName | PageId
1 | name1 | name1 | 1 | book1 | 1
1 | name1 | name1 | 1 | book1 | 2
1 | name1 | name1 | 1 | book1 | 3
1 | name1 | name1 | 2 | book2 | 1
1 | name1 | name1 | 2 | book2 | 2
2 | name2 | name2 | 3 | book3 | 1
2 | name2 | name2 | 3 | book3 | 2
2 | name2 | name2 | 3 | book3 | 3
I found a few ways to implement this (using Linq / create a new flat object). Is there any way to implement this with CsvHealper Class Maps only?
Upvotes: 1
Views: 4095
Reputation: 9074
This appears to work.
public static void Main(string[] args)
{
var records = GetRecords();
using (var csv = new CsvWriter(Console.Out))
{
csv.Configuration.RegisterClassMap<PersonMap>();
csv.Configuration.RegisterClassMap<BookMap>();
csv.Configuration.RegisterClassMap<PageMap>();
csv.WriteHeader<PersonDTO>();
csv.WriteHeader<Book>();
csv.WriteHeader<Page>();
csv.NextRecord();
foreach (var person in records)
{
foreach (var book in person.Books)
{
foreach (var page in book.Pages)
{
csv.WriteRecord(person);
csv.WriteRecord(book);
csv.WriteRecord(page);
csv.NextRecord();
}
}
}
}
Console.ReadKey();
}
public sealed class PersonMap : ClassMap<PersonDTO>
{
public PersonMap()
{
Map(m => m.Id).Name("PersonId");
References<PersonDetailsMap>(m => m.details);
}
}
public sealed class PersonDetailsMap : ClassMap<PersonDetails>
{
public PersonDetailsMap()
{
Map(m => m.FName);
Map(m => m.LName);
}
}
public sealed class BookMap : ClassMap<Book>
{
public BookMap()
{
Map(m => m.Id).Name("BookId");
Map(m => m.Name).Name("BookName");
}
}
public sealed class PageMap : ClassMap<Page>
{
public PageMap()
{
Map(m => m.Id).Name("PageId");
}
}
Upvotes: 6