Вставка большого количества данных в базу данных с помощью LINQ

1

Я хочу вставить около 1 миллиона записей в базу данных, используя Linq в ASP.NET MVC. Но когда я пробую следующий код, он не работает. Это бросает OutOfMemoryException. А также потребовалось 3 дня в цикле. Может кто-нибудь, пожалуйста, помогите мне в этом???

db.Database.ExecuteSqlCommand("DELETE From [HotelServices]");

DataTable tblRepeatService = new DataTable();
tblRepeatService.Columns.Add("HotelCode",typeof(System.String));
tblRepeatService.Columns.Add("Service",typeof(System.String));
tblRepeatService.Columns.Add("Category",typeof(System.String));

foreach (DataRow row in xmltable.Rows)
{
     string[] servicesarr = Regex.Split(row["PAmenities"].ToString(), ";");

     for (int a = 0; a < servicesarr.Length; a++)
     {
         tblRepeatService.Rows.Add(row["HotelCode"].ToString(), servicesarr[a], "PA");
     }

     String[] servicesarrA = Regex.Split(row["RAmenities"].ToString(), ";");

     for (int b = 0; b < servicesarrA.Length; b++)
     {
         tblRepeatService.Rows.Add(row["hotelcode"].ToString(), servicesarrA[b], "RA");
     }
}

HotelAmenties _hotelamenties;

foreach (DataRow hadr in tblRepeatService.Rows)
{
     _hotelamenties = new HotelAmenties();
     _hotelamenties.Id = Guid.NewGuid();
     _hotelamenties.ServiceName = hadr["Service"].ToString();
     _hotelamenties.HotelCode = hadr["HotelCode"].ToString();

     db.HotelAmenties.Add(_hotelamenties);
}

db.SaveChanges();

Таблица tblRepeatService имеет около 1 миллиона строк.

Теги:
sql-server
linq

2 ответа

2
Лучший ответ

Массовые вставки, подобные этому, очень неэффективны в LINQtoSQL. Каждая вставка создает как минимум три объекта (объект DataRow, объект HotelAmenities и запись отслеживания для него), пережевывая память на объекты, которые вам не нужны.

Учитывая, что у вас уже есть DataTable, вы можете использовать System.Data.SqlClient.SqlBulkCopy чтобы подталкивать содержимое таблицы во временную таблицу на SQL-сервере, а затем использовать один оператор insert для загрузки данных в конечный пункт назначения. Это самый быстрый способ, который я нашел, чтобы переместить много тысяч записей из памяти в SQL.

1

Если производительность не имеет значения, и это задание на 1 выстрел, вы можете придерживаться того, как вы используете. Ваша проблема заключается в том, что вы сохраняете только в конце, поэтому сущность Framework должна хранить и генерировать SQL для 1 миллиона операций одновременно, изменять свой код, чтобы вы сохраняли каждые 1000 или около того вставок, а не только в конце, и это должно работать просто отлично.

int i = 0;
foreach (DataRow hadr in tblRepeatService.Rows)
{ 
     _hotelamenties = new HotelAmenties();
     _hotelamenties.Id = Guid.NewGuid();
     _hotelamenties.ServiceName = hadr["Service"].ToString();
     _hotelamenties.HotelCode = hadr["HotelCode"].ToString();

     db.HotelAmenties.Add(_hotelamenties);
     if((i%1000)==0){
     db.SaveChanges();
     }
     i++;
}    
db.SaveChanges();
  • 0
    Не забудьте сбросить контекст и создать новый! Старый все равно хранит ссылки ...
  • 0
    Это может не быть проблемой, мое внутреннее чувство заключается в том, что при создании запроса sql выдается исключение OOM, а не из-за графа объектов, но да, если то, что я опубликовал, не работает, было бы неплохо разделить их на 1K заранее, а затем переместите контекст использования в цикл группы foreach. Если это не решит проблему пользователя, я обновлю свой ответ этим

Ещё вопросы

Сообщество Overcoder
Наверх
Меню