【问题标题】:CsvHelper try to export in csv a list which contain another list .netCsvHelper 尝试在 csv 中导出包含另一个列表 .net 的列表
【发布时间】:2019-11-20 09:08:54
【问题描述】:

我在 .Net Framework 中使用 csvHelper 实现了一个 web api 来导出 csv。

我有课

public class StudentInfo
{
    public Student Student {get;set;}
    public Courses[] Courses { get; set; }
}

public class Student
{
    public string Id {get;set;}
    public string Name{ get; set; }
}

public class Course
{
   public string CourseId {get;set;}
   public string CourseName{ get; set; }
}

我有一个返回列表的方法

public List<StudentInfo> FetchStudentInfo()
{
    //bla bla 
}

现在我想使用 csvHelper 在 csv 中导出列表

这是我的代码

List<StudentInfo> records = _service.FetchStudentInfo()
    using (StreamWriter sw = new StreamWriter(memoryStream))
    {
        using (var csv = new CsvWriter(sw))
        {        
            csv.WriteRecords(records);
            sw.Flush();
        }
    }

但此代码仅导出到 csv 对象学生。 如何为每个学生导出到 csv 以使列表与同一行中的课程?

例如12 jim java c# python

如果我尝试

foreach(var item in records)
{
    csvWriter.WriteRecords(item.Student);//I have compile error because it want to pass an IEnumerable
    csvWriter.WriteRecords(item.Courses);
}

【问题讨论】:

  • CSV 文件存储数据行,每列用逗号分隔。因此它们只能代表一种实体类型。如果要嵌套类型(学生课程),则需要序列化为不同的格式。显而易见的选择是 JSON(Newtonsoft.Json 或 System.Text.Json)。
  • 我建议使用 JSON 或 XML 进行序列化,因为两者都允许比 CSV 更复杂的结构。

标签: c# .net asp.net-web-api csvhelper


【解决方案1】:

@dimmits 答案工作得很好并且易于阅读。我想我会提供另一个更基于配置的选项。它确实需要修改 StudentInfo 类。

public class Program
{
    public static void Main(string[] args)
    {
        var studentInfos = FetchStudentInfo();

        using (var csv = new CsvWriter(Console.Out))
        {
            csv.Configuration.HasHeaderRecord = false;
            csv.Configuration.RegisterClassMap<StudentInfoMap>();

            csv.WriteRecords(studentInfos);
        }

        Console.ReadKey();
    }

    public static List<StudentInfo> FetchStudentInfo()
    {
        Course[] courses1 = { new Course { CourseId = "1", CourseName = "java" }, new Course { CourseId = "2", CourseName = "c#" }, new Course { CourseId = "3", CourseName = "python" } };
        Course[] courses2 = { new Course { CourseId = "1", CourseName = "java" }, new Course { CourseId = "2", CourseName = "c#" } };
        return new List<StudentInfo>
        {
            new StudentInfo{ Student = new Student{Id = "12", Name = "Jim"}, Courses = courses1 },
            new StudentInfo{ Student = new Student{Id = "45", Name = "Dave"}, Courses = courses2 }
        };
    }
}

public class StudentInfoMap : ClassMap<StudentInfo>
{
    public StudentInfoMap()
    {
        References<StudentMap>(m => m.Student);
        Map(m => m.CourseNames).Index(3);
    }
}

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

public class StudentInfo
{
    public Student Student { get; set; }
    public Course[] Courses { get; set; }
    public string[] CourseNames { get { return Courses.Select(c => c.CourseName).ToArray(); } }
}

public class Student
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Course
{
    public string CourseId { get; set; }
    public string CourseName { get; set; }
}

【讨论】:

  • 非常感谢大卫,我接受您的评论作为解决方案。这是非常好的方法!
【解决方案2】:

CSV 格式不能代表列表中的列表。导出后读取 CSV 时,我不知道如何解释数据。

必须首选 XML 或 JSON 将复杂数据导出到平面文件中。

如果您真的想获取 CSV 文件,则必须使用 2 个不同的分隔符来区分 2 个类(例如:StudentInfo 的“,”和课程的“;”)。

在我创建一个代表 CSV 数据的类之后:

public class StudentInfoCsv
{
    public Student Student {get;set;}
    public string Courses { get; set; }
}

List<StudentInfoCsv> csvData = new List<StudentInfoCsv>
foreach(var item in records)
{
    StudentInfoCsv.Add(new StudentInfoCsv()
    {
        Student = item.Student,
        Courses = CsvSerializer.SerializeToCsv(item.Courses)
    }
}
csvWriter.WriteRecords(csvData);

【讨论】:

    【解决方案3】:

    解决办法是

                           foreach (StudentInfo item in records)
                            {
                                csvWriter.WriteField(item.Student.Id);
                                csvWriter.WriteField(item.Student.Name);
    
                                foreach (var row in item.Courses)
                                {
                                    csvWriter.WriteField(row.CourseName);
                                }
                                csvWriter.NextRecord();
                            }
    

    输出将是

    12 jim java c# python

    【讨论】:

      猜你喜欢
      • 2020-03-10
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 1970-01-01
      • 2012-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多