db.SaveChanges() in loop doesn't save records after an error

时间:2016-06-18 20:22:21

标签: c# asp.net-mvc entity-framework epplus ora-00001

I want to import data from Excel to DataBase using EPPLUS. From here I took code: https://www.paragon-inc.com/resources/blogs-posts/easy_excel_interaction_pt6

using (var db = new DbEntities())
{
    for (var row = 2; row <= lastRow; row++)
    {
        var newRecord = new DB_USER
        {
            ID = Int32.Parse(worksheet.Cells[idColumn + row].Value.ToString()),
            FIRST_NAME = worksheet.Cells[firstNameColumn + row].Value.ToString(),
            LAST_NAME = worksheet.Cells[lastNameColumn + row].Value.ToString(),                               
        };

        db.DB_USER.Add(newRecord);
        try
        {
            db.SaveChanges();
            totalImported++;
        }
        catch (Exception ex)
        {
            resultMessages.Add(string.Format("Error in line #{0}: {1}\n", row,
                ex.Message));
        }
    }
}

Everything works fine if data in excel are correct. Problem is if any record has invalid data. For example, we have 3 records in excel:

  • ID: 21 (ID not in base)| FIRST NAME: John | LAST NAME: Cage
  • ID: 1 (ID is in base) | FIRST NAME: Mei | LAST NAME: Blue
  • ID: 25 (ID not in base) | FIRST NAME: Nick | LAST NAME: Siri

And in database is already record with ID = 1. So 1st and 3rd should save, but 2nd shouldn't. The problem is that only first record is saving, the rest (2nd and 3rd) will get an error. I don't know why? Maybe because it's one transaction or what? It's weird. Can anyone tell me what should I do to save 1st and 3rd record? Not only 1st in this case?


Error:

ORA-00001: unique constraint primary key violated

what doesn't make any sense in 3rd record...

2 个答案:

答案 0 :(得分:0)

为什么不对数据库进行检查,看看数据库中是否有用户具有特定ID,如果用户不存在则只进行插入:

  bool exists = db.DB_USER.Where(u => u.ID == newRecord.ID).Any();

    if(!exists)
    {
        //Do the insert
    }

答案 1 :(得分:-1)

您不应该在代码中设置ID。在数据库中,将ID设置为自动增量..当然,在您的模型中仍然有它,但不是在您的逻辑中

这样,您不需要考虑处理ID,而是让实体框架处理它

无论如何,这里有关于如何更改代码的想法:

        using (var db = new DbEntities())
            {
                foreach (user in db)
                {
                    var userExists = db.DB_USER.Where(u => u.ID == user.ID);

                    if(!userExists)
                    {
                        var newUser = new DB_USER
                        {
                                ID = Int32.Parse(worksheet.Cells[idColumn + row].Value.ToString()),
                                FIRST_NAME = worksheet.Cells[firstNameColumn + row].Value.ToString(),
                                LAST_NAME = worksheet.Cells[lastNameColumn + row].Value.ToString(),                               
                        };

                        try
                        {
                            db.DB_USER.Add(newUser);
                            db.SaveChanges();
                            totalImported++;
                        }
                        catch (Exception ex)
                        {
                             resultMessages.Add(string.Format("Error in line #{0}: {1}\n", row,
                             ex.Message));
                        }
                    }
                }
            }

我的猜测仍然是因为问题中的代码是从第三行开始的(这似乎是对ID 21的影响) 在你改变它之前,它可能会让你认为这是第一行工作正常。

如果刷新数据库,可能已经在ID为21的数据库中有一个条目,并且在您更改之后 它到25,并运行你可能现在有一个25的代码,并再次得到相同的错误。

我在代码中添加了一个foreach循环并检查条目是否存在,因此代码应避免使用主代码 关键违规。

我也在try-catch块中移动它:

db.DB_USER.Add(newUser);
相关问题