2016-06-18 8 views
0

Я хочу импортировать данные из Excel в базу данных с помощью EPPLUS. Отсюда я взял код: https://www.paragon-inc.com/resources/blogs-posts/easy_excel_interaction_pt6db.SaveChanges() в цикле не сохраняет записи после ошибки

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)); 
     } 
    } 
} 

Все отлично работает, если данные в Excel являются правильными. Проблема в том, что какая-либо запись имеет неверные данные. Например, у нас есть 3 записей в Excel:

  • ID: 21 (ID не в базе) | ПЕРВОЕ ИМЯ: Джон | ПОСЛЕДНИЕ ИМЯ: Кейдж
  • ID: 1 (ID в базе) | ПЕРВОЕ ИМЯ: Мэй | ПОСЛЕДНИЕ ИМЯ: Синий
  • ID: 25 (ID не в базе) | ПЕРВОЕ ИМЯ: Ник | ПОСЛЕДНИЕ ИМЯ: Siri

И в базе данных уже есть запись с ID = 1. Итак, 1-й и 3-й должны сэкономить, но 2-й не должен. Проблема в том, что сохраняется только первая запись, остальные (2-й и 3-й) получат ошибку. Я не знаю почему? Может быть, потому что это одна транзакция или что? Это странно. Может ли кто-нибудь сказать мне, что мне делать, чтобы сохранить 1-й и 3-й записи? Не только 1-й в этом случае?


Ошибка:

ORA-00001: unique constraint primary key violated

, что не имеет никакого смысла в 3-й записи ...

+0

В частности, какую ошибку вы получаете? Мы не можем вам помочь, если вы оставите критическую информацию. – mason

+0

@mason, Edited, теперь вы можете увидеть сообщение об ошибке, но до сих пор нет смысла – DiPix

+0

@DiPix: Вы получили эту работу? –

ответ

-1

Вы shouldn't набор 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 прежде чем вы его изменили, возможно, вам показалось, что это был первый ряд, который отлично работал.

Если вы обновите свою базу данных, возможно, уже есть запись в базе данных с идентификатором 21 и после того, как вы изменили на 25 и запустили код, который, вероятно, теперь у вас есть с 25, и снова получите ту же ошибку.

Я добавил цикл foreach к коду и проверил наличие записей, поэтому код должен избегать основного нарушения .

Я также переместить это внутри блока примерки поймать:

db.DB_USER.Add(newUser); 
+0

Это не тот ответ, которого я ожидал. Потому что это не моя база данных, и я не могу изменить структуру. – DiPix

+0

ok, причина, по которой вторая и третья дает ошибку, вероятно, потому, что они уже существуют .. Первая строка не существует сначала, но когда вы ее создаете, добавляется третья возможность, поскольку вы уже добавили строку с этим идентификатором в первая строка. И как вы указали, что идентификатор второй строки уже существовал заранее О, вы обновили вопрос, чтобы включить ошибку сейчас .. Это нарушение первичного ключа, а первичный ключ, вероятно, ID. Вы не можете добавлять строки с первичным ключом, который уже существует, поэтому вам нужно проверить, существует ли он первым, прежде чем пытаться добавить строку –

+0

. Ой, в сообщении выше была ошибка. 1-я и 3-я записи имеют различный идентификатор, а в базе не их. – DiPix

0

Почему вы не делаете проверку в базе данных, чтобы увидеть, если там уже есть пользователь в базе данных с и только с определенным ID сделайте вставку, если пользователь не существует:

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

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

Конечно, я могу, но что, если будет сложнее Secondkeys ? – DiPix

+0

Ну, как правило, ссылки на внешние ключи не вызывают проблем с вставкой, например, если у вас есть свойство в пользовательском объекте с именем UserTypeID, вы можете вставить столько пользователей, сколько хотите, с помощью UserTypeID = 1.Вы получите ошибку из-за первичной ключевое нарушение, так что я дал вам решение проблемы, у вас есть –

+0

Вы правы, но что делать, если в excel данных будет строка вместо int в столбце ID? Попробуйте поймать это с этим. В вашем решении я должен работать с этим с помощью linq. Если вы понимаете, о чем я? – DiPix