#sql-server #database #ado.net #identity #sqlbulkcopy
#sql-сервер #База данных #ado.net #идентификатор #sqlbulkcopy
Вопрос:
У меня проблема.СЕТЬ DataTable
насчитывает около 100 000 записей. В этой таблице есть столбец, xyID
в котором нет значений, поскольку столбец является автоматически сгенерированным IDENTITY
в моей базе данных SQL Server.
Мне нужно получить сгенерированные идентификаторы для других процессов. Я ищу способ массового копирования этого DataTable
в базу данных SQL Server и на том же «шаге» «заполнить» мои DataTable
сгенерированные идентификаторы.
Как я могу получить значения идентификаторов записей, вставленных в таблицу, используя SqlBulkCopy
класс?
Ответ №1:
В настоящее время я делаю что-то вроде этого:
DataTable objects = new DataTable();
DataColumn keyColumn = new DataColumn("name", typeof(string));
DataColumn versionColumn = new DataColumn("version", typeof(int));
versionColumn.DefaultValue = iVersionID;
objects.Columns.Add(keyColumn);
objects.Columns.Add(versionColumn);
foreach (KeyValuePair<string, NamedObject> kvp in Directory)
{
NamedObject o = kvp.Value;
DataRow row = objects.NewRow();
row[0] = o.Name;
objects.Rows.Add(row);
}
using (SqlBulkCopy updater = new SqlBulkCopy(conn,
SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.UseInternalTransaction, null))
{
updater.DestinationTableName = "object_table";
updater.WriteToServer(objects);
}
string sQuery = @"SELECT id, name FROM object_table WHERE version = @ver";
using (SqlCommand command = new SqlCommand(sQuery, conn))
{
SqlParameter version = new SqlParameter("@ver", SqlDbType.Int, 4);
version.Value = versionID;
command.Parameters.Add(version);
command.CommandTimeout = 600;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
string key = (string)reader[1];
NamedObject item = Directory[key];
item.ID = (int)reader[0];
}
}
}
Обратите внимание, что наш дизайн данных позволяет фильтровать все наши новые объекты с помощью идентификатора версии; каждая добавляемая нами строка будет иметь тот же идентификатор версии, и мы ранее удалили все строки в базе данных, у которых уже был этот идентификатор версии.
Однако время ожидания моего запроса select в ExecuteReader в настоящее время истекает, даже при этом 10-минутном окне. Итак, это не наше окончательное решение.
Комментарии:
1. На самом деле мы в конечном итоге сохранили это решение, решив проблемы с таймаутом, настроив процесс на истечение срока действия старых и нерелевантных данных. Я добавил столбец метки времени и столбец флага «сохранить» в таблицу версий и добавил режим, который удаляет все данные, связанные с версиями старше месяца, без флага «сохранить». Наши проблемы с таймаутом исчезли после удаления ~ 100 миллионов строк.