【问题标题】:Upload CSV data into SQL database using ASP.NET Core MVC使用 ASP.NET Core MVC 将 CSV 数据上传到 SQL 数据库
【发布时间】:2022-11-22 09:18:31
【问题描述】:

我正在尝试将 .csv 文件中的数据插入到我的数据库中,但无论何时我上传数据,记录都是空的。

到目前为止,这是我的代码:

[HttpPost]
public async Task<IActionResult> ImportFromExcel(IFormFile formFile)
{
    var data = new MemoryStream();
    await formFile.CopyToAsync(data);

    data.Position = 0;
    TextReader reader = new StreamReader(data);

    var csvReader = new CsvReader(reader, new CsvConfiguration(System.Globalization.CultureInfo.CurrentCulture)
                        {
                            HasHeaderRecord = true,
                            HeaderValidated = null,
                            MissingFieldFound = null
                        });

    var Name = csvReader.GetField(0).ToString();
    var dep = "cccccccccc";
    var pos = "bbbbbbbbbbb";

    await dcx.Participants.AddAsync(new Participant
                                        {
                                            Name = Name,
                                            Position = pos,
                                            Department = dep,
                                        });
    dcx.SaveChanges();
    
    return ViewComponent("ViewParticipants");
}

这是我的数据库表中的示例数据:

【问题讨论】:

  • csv 未保存在服务器上,我也不想将其保存在服务器上。我只想上传和读取数据
  • 你永远不会打电话给csvReader.Read()来阅读第一行。参见How to use CSV Helper to read line by line in c#?
  • 您还应该通过 using 声明正确处理您的 StreamReaderCsvReader

标签: asp.net-core asp.net-core-mvc csvhelper


【解决方案1】:

只要 CSV 的标题与数据库中列的名称相匹配,您就应该能够执行类似的操作。如果名称不匹配,您可以使用 ParticipantMap 中的 .Name("CsvColumnName") 添加 CSV 文件中的列名称。示例:Map(r =&gt; r.Description).Name("MyCsvDescription");

[HttpPost]
public async Task<IActionResult> ImportFromExcel(IFormFile formFile)
{
    var data = new MemoryStream();
    await formFile.CopyToAsync(data);

    data.Position = 0;

    var conf = new CsvConfiguration(CultureInfo.InvariantCulture)
    {
         HasHeaderRecord = true,
         HeaderValidated = null,
         MissingFieldFound = null,
         BadDataFound = context =>
         {
              bad.Add(context.RawRecord);
         }
    };
    using (TextReader reader = new StreamReader(data))
    using (var csvReader = new CsvReader(reader, config)) {

        csvReader.Context.RegisterClassMap<ParticipantMap>();
        var records = csvReader.GetRecords<Participant>().ToList();

        var dep = "cccccccccc";
        var pos = "bbbbbbbbbbb";

        records.ForEach(r =>
        {
            r.Department = dep;
            r.Position = pos;
        });

        await dcx.Participants.AddRangeAsync(records);
        dcx.SaveChanges();
    }
    
    return ViewComponent("ViewParticipants");
}

public class ParticipantMap : ClassMap<Participant>
{
    public ParticipantMap()
    {
        AutoMap(CultureInfo.InvariantCulture);
        Map(r => r.Department).Ignore();
        Map(r => r.Position).Ignore();
    }
}

【讨论】:

    【解决方案2】:

    在我看来,你应该先调用csvReader.Read()来读取文件行。

    可以参考下面的测试代码,效果很好。

    [HttpPost]
    public async Task<IActionResult> ImportFromExcel(IFormFile formFile)
    {
         var data = new MemoryStream();
         await formFile.CopyToAsync(data);
    
         data.Position = 0;
         using (var reader = new StreamReader(data))
         {
               var bad = new List<string>();
               var conf = new CsvConfiguration(CultureInfo.InvariantCulture)
               {
                    HasHeaderRecord = true,
                    HeaderValidated = null,
                    MissingFieldFound = null,
                    BadDataFound = context =>
                    {
                         bad.Add(context.RawRecord);
                    }
               };
               using (var csvReader = new CsvReader(reader, conf))
               {
                    while (csvReader.Read())
                    {
                         var Name = csvReader.GetField(0).ToString();
                         var pos = csvReader.GetField(1).ToString();
                         var dep = csvReader.GetField(2).ToString();
                            
                         await dcx.Participants.AddAsync(new Participant
                         {
                              Name = Name,
                              Position = pos,
                              Department = dep,
                         });
                         dcx.SaveChanges();
                    }
               }
         }
         return ViewComponent("ViewParticipants");
    }
    

    测试结果:

    【讨论】:

    • 谢谢@Chen,你的回答帮了大忙。我很感激。但是它可以读取的数据有限制吗?
    • 在我看来,CsvHelper 没有施加任何限制。如果遇到问题,您可以尝试不执行 ToList() 并将其放入循环中。这将一次拉出一条记录。在循环中设置一个断点,看看你是否得到了那样的东西。如果是这样,做一个计数器,看看它拉了多少条记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    • 2021-05-31
    • 2011-05-02
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    相关资源
    最近更新 更多