Я хочу вставить около 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 миллиона строк.
Массовые вставки, подобные этому, очень неэффективны в LINQtoSQL. Каждая вставка создает как минимум три объекта (объект DataRow
, объект HotelAmenities
и запись отслеживания для него), пережевывая память на объекты, которые вам не нужны.
Учитывая, что у вас уже есть DataTable
, вы можете использовать System.Data.SqlClient.SqlBulkCopy
чтобы подталкивать содержимое таблицы во временную таблицу на SQL-сервере, а затем использовать один оператор insert
для загрузки данных в конечный пункт назначения. Это самый быстрый способ, который я нашел, чтобы переместить много тысяч записей из памяти в SQL.
Если производительность не имеет значения, и это задание на 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();
SqlBulkCopy
для массовых операций - Linq-to-EF не оптимизирован и не предназначен для массовых операций. См. Соответствующие документы MSDN для деталей