#c# #sql-server #ado.net #sqlbulkcopy
#c# #sql-сервер #ado.net #sqlbulkcopy
Вопрос:
Я получаю результаты запроса из Azure Log Analytics. Результаты находятся в Table
объекте. Все это в строковом формате. В базе данных таблица имеет столбец PeriodStart
, который является smalldatetime
типом.
Приведенный ниже код работает нормально — он вставляет все данные. Но он преобразует PeriodStart
неправильно. Например, у меня есть строковое значение в строке для PeriodStart
столбца "2019-03-26T00:00:00Z"
— и в базе данных оно будет выглядеть "2019-03-26 02:00:00"
. Похоже, что он использует мой часовой пояс — преобразует в местное время. Как этого избежать?
public async Task BulkInsertMetrics(Table metrics)
{
var metricsDt = new DataTable();
metricsDt.Columns.AddRange(metrics.Columns
.Select(c => new DataColumn(c.Name)).ToArray());
foreach (var row in metrics.Rows)
{
metricsDt.Rows.Add(row.ToArray());
}
using (var connection = new SqlConnection(_databaseSettings.ConnectionString))
{
await connection.OpenAsync();
using (var transaction = connection.BeginTransaction())
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction))
{
bulkCopy.DestinationTableName = "Metrics";
foreach (var column in metrics.Columns)
{
bulkCopy.ColumnMappings.Add(column.Name, column.Name);
}
await bulkCopy.WriteToServerAsync(metricsDt);
transaction.Commit();
}
}
}
Комментарии:
1. Используйте строго типизированный столбец datetime в качестве исходного DataTable, чтобы избежать проблем с синтаксическим анализом и форматированием строк.
2. Хорошо, преобразование вручную помогло. Я использовал
ToUniversalTime()
после разбора строки. Спасибо.3. Я расширил ваше решение ответом.
Ответ №1:
Когда вы передаете строку даты и времени, она должна быть проанализирована клиентским API и преобразована в целевой smalldatetime
тип данных, который не имеет понятия о часовом поясе. .NET распознает строку даты и времени ISO 8601 с буквой «Z», обозначающей UTC, и по умолчанию преобразует ее в ваше местное время. А именно:
DateTime.Parse("2019-03-26T00:00:00Z") //converted to your local time
DateTime.Parse("2019-03-26T00:00:00") //no conversion
Одним из обходных путей является использование ToUniversalTime()
метода, позволяющего избежать преобразования в ваш местный часовой пояс:
DateTime.Parse("2019-03-26T00:00:00Z").ToUniversalTime()
Обычно рекомендуется использовать DataTable
с собственными типами данных, содержащими желаемое значение, чтобы вы имели полный контроль над фактическим значением, вставленным в базу данных.