【问题标题】:How to Insert to DB from CVS file using Loop statement如何使用循环语句从 CSV 文件插入数据库
【发布时间】:2020-01-29 08:40:37
【问题描述】:

我的代码有问题。我使用上传的逗号分隔 (CSV) 文件插入我的数据库,其中包含 5 行。第一行成功插入数据库,但在第二个循环插入第二行时遇到错误:

当 IDENTITY_INSERT 设置为 OFF 时,无法为表“bdoToDbs”中的标识列插入显式值。

这是我的循环代码

            while (i < users.Count)
            {
                ViewBag.CompanyCode = users[i].CompanyCode;
                ViewBag.ProductCode = users[i].ProductCode;
                ViewBag.TransactionDate = users[i].TransactionDate;
                ViewBag.TransactionTime = users[i].TransactionTime;
                ViewBag.OriginatingBranch = users[i].OriginatingBranch;
                ViewBag.CustomerNumber = users[i].CustomerNumber;
                ViewBag.TransactionOrigin = users[i].TransactionOrigin;
                ViewBag.TypeOfPayment = users[i].TypeOfPayment;
                ViewBag.CheckNumber = users[i].CheckNumber;
                ViewBag.TransactionAmount = users[i].TransactionAmount;
                ViewBag.CustomerName = users[i].CustomerName;

                bdoToDb.CompanyCode = ViewBag.CompanyCode;
                bdoToDb.ProductCode = ViewBag.ProductCode;
                bdoToDb.TransactionDate = ViewBag.TransactionDate;
                bdoToDb.TransactionTime = ViewBag.TransactionTime;
                bdoToDb.OriginatingBranch = ViewBag.OriginatingBranch;
                bdoToDb.CustomerNumber = ViewBag.CustomerNumber;
                bdoToDb.TransactionOrigin = ViewBag.TransactionOrigin;
                bdoToDb.TypeOfPayment = ViewBag.TypeOfPayment;
                bdoToDb.CheckNumber = ViewBag.CheckNumber;
                bdoToDb.TransactionAmount = ViewBag.TransactionAmount;
                bdoToDb.CustomerName = ViewBag.CustomerName;
                bdoToDb.UserName = ViewBag.DisplayName;
                bdoToDb.UserIP = HttpContext.Connection.RemoteIpAddress.ToString();
                bdoToDb.UserDate = DateTime.Now.ToString("MM/dd/yyyy");
                i++;
                _context.Add(bdoToDb);
                await _context.SaveChangesAsync();
            });
            return RedirectToAction(nameof(Index));
        }

【问题讨论】:

标签: c# asp.net-core-mvc entity-framework-core asp.net-core-2.2 csvhelper


【解决方案1】:

EF 核心的优点之一是它可以跟踪更改,然后您可以通过保存一次提交所有这些更改。如果你移动了

       await _context.SaveChangesAsync();

在您的 while 循环之外(已编辑:并根据下面的精明评论在每次迭代中构造一个新对象),它将起作用。在身份插入表的情况下,您不设置对象的 ID,但是为了能够知道该 ID 最终是什么,在调用保存更改后,它会更新对象的 ID 字段。因此,在您第一次保存后,ID 字段设置为下一个 ID,然后您更新对象上的所有属性,然后使用 .Add 尝试插入它,但 ID 已设置并标记为已修改。您也可以通过每次构造一个新的对象实例来解决这个问题,或者 EF 有办法清除该 ID 并将其标记为未修改......但我建议您将保存移到最后,因为它可能会更多高效的。如果这是针对非常大量的数据,也许每次传递 1000 条左右的记录时都会保存,但除非数据量很大,否则不用担心。

对于后续查询,大致如下:(您实际上只需要不同的对象实例,因为 EF 将它们存储在内存中)

            ViewBag.TransactionAmount = users[i].TransactionAmount;
            ViewBag.CustomerName = users[i].CustomerName;

            // added constructor
            bdoToDb = new BdoToDb(); // <- don't know name of your class

            bdoToDb.CompanyCode = ViewBag.CompanyCode;
            bdoToDb.ProductCode = ViewBag.ProductCode;

【讨论】:

  • 如果我这样做,它只会将 CSV 的最后一行保存到数据库中,而不是所有行。
  • @josebalerosjr 主要问题是您在每次迭代中重复使用 bdoToDb 实例。
  • @josebalerosjr 这是英孚。只要上下文存在,每个实体都必须有自己的对象。为每个插入创建一个新的 bdoToDb 对象。
  • 好点,@josebalerosjr。猜猜你无论如何都需要构造一个新对象。
  • @VictorThomasWilcoxJr。谢谢你。我的代码现在可以工作了。我将bdoToDb = new BdoToDb(); 添加到我以前的代码中,它工作得很好。非常感谢。
猜你喜欢
  • 2018-04-05
  • 1970-01-01
  • 2019-04-14
  • 1970-01-01
  • 1970-01-01
  • 2010-09-05
  • 1970-01-01
  • 2021-11-09
  • 2016-11-03
相关资源
最近更新 更多