2

Я использую EF5 для переноса некоторых данных из одной базы данных в другую. Я бы обычно использовал SQL для чего-то подобного, но мне нужны другие функции (например, создание пользователей в MembershipProvider) и надеялся сделать все это в EF. Я мигрируют около 100к строк и использовать это, чтобы сделать это:EntityFramework Операция ожидания, рассчитанная по длительной задаче

 using (var connection = new SqlConnection(connectionString)) 
     { 
      using(var command = new SqlCommand(commandText, connection)) 
      { 
       connection.Open(); 
       using (SqlDataReader reader = command.ExecuteReader()) 
       { 
        while (reader.Read()) 
        { 
         var employer = new Employer(); 

         employer.EAN = reader["EAN"].ToString(); 

         employer.Name = GetString(reader["EmpName"]); 

         employer.TaxMailingAddress = new Address 
         { 
          StreetAddress = GetString(reader["Street"]), 
          City = GetString(reader["City"]), 
          State = GetString(reader["USState"]), 
          ZipCode = GetString(reader["Zip"]) 
         }; 

         employer.TaxMailingAddress.SaveOrUpdate(); 
         employer.SaveOrUpdate(); // This is where the timeout happens 

         string dba = GetString(reader["DBA"]); 
         if (!string.IsNullOrWhiteSpace(dba)) 
         { 
          employer.AddDBA(new EmployerDba 
          { 
           Name = dba 
          }); 
         } 

         string email = GetString(reader["Email"]); 
         if (!string.IsNullOrWhiteSpace(email)) 
         { 
          var user = CreateNewUser(email); 

          if (user != null) 
          { 
           user.AddAuthorizedEmployer(employer); 

           user.AddRole(EmployerRole.Admin, employer, true); 
          } 
         } 
        } 
       } 
      } 
     } 

Мой SaveOrUpdate метод довольно прост:

public void SaveOrUpdate() 
    { 
     using (var db = new MyContext()) 
     { 
      if (db.Employers.FirstOrDefault(x => x.EAN == EAN && x.Id != Id) != null) 
       throw new Exception("An employer with this EAN has already been registered."); 

      var employer = new Employer(); 

      if (Id == 0) 
      { 
       db.Employers.Add(employer); 

       employer.CreatedBy = Statics.GetCurrentUserName(); 
       employer.DateCreated = DateTime.Now; 
      } 
      else 
      { 
       employer = db.Employers.FirstOrDefault(x => x.Id == Id); 

       employer.ModifiedBy = Statics.GetCurrentUserName(); 
       employer.DateModified = DateTime.Now; 
      } 

      employer.EAN = EAN; 
      employer.Name = Name; 
      if (TaxMailingAddress != null) employer.TaxMailingAddress = db.Addresses.FirstOrDefault(x => x.Id == TaxMailingAddress.Id); 
      if (SingleSeparationStatementAddress != null) employer.SingleSeparationStatementAddress = db.Addresses 
            .FirstOrDefault(x => x.Id == SingleSeparationStatementAddress.Id); 

      db.SaveChanges(); 

      Id = employer.Id; 
     } 
    } 

Задача должна занять около 2,5 часов. Тем не менее, после запуска многих тысяч строк, иногда 80k, иногда до 7k, я получаю это исключение "The wait operation timed out", всегда на employer.SaveOrUpdate();. Может ли это иметь какое-либо отношение к тому, насколько близко к employer.TaxMailingAddress.SaveOrUpdate();? Есть ли «дождаться завершения транзакции»? Возможно, убедитесь, что соединение действительно, и если вы не пытаетесь воссоздать его или что-то еще? Спасибо за любую помощь.

+1

По умолчанию для любых команд, запускаемых с БД, есть таймаут 30/60 секунд. Вы можете переопределить этот параметр в своем DbContext. См. Http://stackoverflow.com/questions/10549640/how-to-set-commandtimeout-for-dbcontext. Тем не менее, делать такие вещи в чистом EF - не самая лучшая идея. – Kittoes0124

+0

@ Kittoes +1 EF добавляет огромные накладные расходы на ваш процесс. Каждый кусок передаваемых данных собирается использовать память, поскольку она преобразуется в объект. – Aron

+0

Да, хотя EF является одним из моих любимых инструментов, когда-либо созданных, у него все еще есть время и место. Бывают случаи, когда я загружаю данные, подобные этим, но они всегда являются одноразовыми сценариями. Процессы, подобные описанным выше, НИКОГДА не должны вносить его в производство. – Kittoes0124

ответ

3

Проблема заключалась в том, что мое первоначальное соединение с базой данных, которое использовалось для подключения к другой базе данных, из которой я получал данные для импорта, было отключено. Поэтому я закончил цикл всех операторов reader.Read() и поместил их в массив. Затем я зациклился на этом массиве, чтобы фактически обрабатывать и сохранять данные в моей новой базе данных.

Смежные вопросы