Доступ к TimeZoneInfo из SQL 2005 Server - PullRequest
8 голосов
/ 05 марта 2009

Класс .NET TimeZoneInfo великолепен, и я подумал, что он решит все мои проблемы с записью данных из нескольких часовых поясов в моей базе данных SQL 2005.

Чтобы преобразовать дату и время UTC в базе данных в любой другой часовой пояс, я просто поместил бы часовой пояс в класс TimeZoneInfo, используя TimeZoneInfo.FindSystemTimeZoneById (), а затем вызвал TimeZoneInfo.ConvertTimeFromUtc (). Brilliant! Я бы просто назвал это из SQL .NET CLR!

НО ... TimeZoneInfo имеет атрибут защиты хоста MayLeakOnAbort.

Когда я использую VS 2008 для создания SQL-функции или хранимой процедуры, я даже не вижу system.TimeZoneInfo класс никогда не использует его. Я также предполагаю, что даже если бы я мог как-то ссылаться на класс TimeZoneInfo, я бы, вероятно, получил какое-то исключение безопасности, если бы попытался зарегистрировать сборку в SQL Sever 2005.

Помощь! Есть ли способ получить доступ к классу TimeZoneInfo и всем его богатствам из SQL Server 2005?

NB. Я только что добавил это предупреждение после первого ответа:

У нас есть сайты в разных местах по всему миру. Нам необходимо хранить местное время и время UTC в базе данных относительно событий, которые могут потребовать изменения на уровне сайта. Тренд может состоять из более чем 52 000 точек данных в год, поэтому для эффективности я не могу просто хранить времена в UTC в БД и преобразовывать каждую точку данных на клиенте. Таким образом, мне нужна возможность в БД преобразовывать местное время в любом часовом поясе во время UTC и обратно.

Ответы [ 7 ]

3 голосов
/ 25 сентября 2012

Я только что закончил делать это в базе данных SQL 2008.

Сначала я должен был установить надежность базы данных и убедиться, что владелец был прав.

use [myDB]
go
alter database [myDB] set trustworthy on
go

exec sp_changedbowner 'sa'
go

Затем я создал решение .NET

Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Collections.ObjectModel
Imports System.Runtime.InteropServices

Partial Public Class StoredProcedures
    <Microsoft.SqlServer.Server.SqlProcedure()> _
    Public Shared Sub sp_ConvertTime(ByVal UTCTime As DateTime, ByVal ZoneID As String, <Out()> ByRef Output As DateTime)
    Dim sp As SqlPipe = SqlContext.Pipe

    Dim ConvertedTime As DateTime
    Dim tzUTC = TimeZoneInfo.FindSystemTimeZoneById("UTC")
    Dim tzNew = TimeZoneInfo.FindSystemTimeZoneById(ZoneID)

    ConvertedTime = TimeZoneInfo.ConvertTime(UTCTime, tzUTC, tzNew)

    Output = ConvertedTime
    sp.Send(ConvertedTime)

    ConvertedTime = Nothing
    tzUTC = Nothing
    tzNew = Nothing
    sp = Nothing

End Sub
End Class

Перед развертыванием я установил уровень разрешений Небезопасный .

Затем я развернул его, проверил окно «Вывод» на наличие ошибок сборки и исправил их.

Вот тест SQL

DECLARE @UTCTime datetime
DECLARE @ZoneID varchar(21)
DECLARE @NewTime datetime

SET @UTCTime = GETUTCDATE()
SET @ZoneID = 'Central Standard Time'

exec sp_ConvertTime @UTCTime, @ZoneID, @NewTime OUTPUT
select @NewTime AS NewTime
1 голос
/ 19 марта 2010

Вот решение:

  1. Создайте хранимую процедуру CLR или UDF, которая обернет функциональность класса TimeZoneInfo. Следуйте этому руководству: http://www.codeproject.com/KB/cs/CLR_Stored_Procedure.aspx
  2. TimeZoneInfo требует .NET 3.5. Однако System.Core v3.5 не пройдет проверку в Sql Server 2005. Поэтому необходимо выполнить CREATE ASSEMBLY для System.Core. Подробнее: http://weblogs.asp.net/paulomorgado/archive/2009/06/13/playing-with-sql-server-clr-integration-part-iv-deploying-to-sql-server-2005.aspx

Обратите внимание, что вам нужно зарегистрировать System.Core как UNSAFE ... так что у вашего администратора может быть с этим проблема.

Более того, даже если вы развертываете на Sql Server 2008 (который включает в себя .NET 3.5), ваша пользовательская сборка должна быть UNSAFE, поскольку она использует небезопасные методы из TimeZoneInfo: http://social.msdn.microsoft.com/Forums/en/sqlnetfx/thread/d0515862-eb87-4a13-bab4-0e343983823a

Я попробовал это и получил сообщение о MayLeakOnAbort.

Если UNSAFE в вашей среде нормально, вы должны это сделать.

1 голос
/ 25 марта 2009

Я столкнулся с этой же проблемой, потому что хотел выполнить преобразование между локальным и UTC в запросе, который использовался службами отчетов. Я прошел через то, что, кажется, точно такое же сражение, как вы проходите с этим. Мое решение ...

Я начал писать отдельное приложение, которое просматривало объект TimeZoneInfo и записывало записи в таблицу TimeZoneInfo в моей базе данных. Я сохранил все смещения (включая смещения при переходе на летнее время) для каждого года от начального до конечного года (это были аргументы для отдельного приложения).

Из этой таблицы я смог создать некоторые функции sql, которые будут принимать дату в utc или local и timezone, использовать таблицу поиска TimeZoneInfo, чтобы получить правильное смещение для правильного времени года и часового пояса, и вернуть дата и время конвертируются в UTC или местное.

К сожалению, я еще не закончил. Мне пришлось создать функцию CLR, которая возвращала бы текущий часовой пояс системы, используя библиотеку, безопасную для SQL Server (в отличие от объекта TimeZoneInfo). В данный момент у меня нет доступа к моему коду, но я полагаю, что использовал объект TimeZone.

http://msdn.microsoft.com/en-us/library/system.timezone_members.aspx

Подводя итог, у меня была функция CLR, которая возвращала часовой пояс системы, приложение, которое создавало таблицу поиска часовых поясов с конкретной информацией DLS за диапазон лет. Я завершил все это с помощью хранимой процедуры, которая заняла временную зону и дату для преобразования, и с тех пор она прекрасно работает.

Я понимаю, что это ОГРОМНАЯ работа по созданию чего-то, что казалось довольно простым, но оно выполнило работу безопасно.

1 голос
/ 05 марта 2009

Я не знаю, можно ли получить доступ к классу TimeZoneInfo из SQL, но обычно считается хорошей практикой придерживаться UTC в базе данных, когда клиент выполняет преобразование в местное время.

Таким образом, каждый раз, когда вы пишете в базу данных, вы переводите из местного времени в UTC, каждый раз, когда вы читаете из базы данных, вы переводите из UTC в местное время.

РЕДАКТИРОВАТЬ: Исходя из того, что я понимаю проблемы, решение, которое я бы по-прежнему рекомендовал:

1) Сохраните даты в UTC в базе данных. 2) Рассчитать местное время на клиенте.

2 можно сделать несколькими способами. Рекомендуемый способ - установить для DateTimeMode значение Local (или Utc) в классе DataColumn (*). Если вам нужен отчет по местному времени, используйте Local, если вам нужен UTC, используйте UTC.

(*) Обратите внимание, что в Visual Studio существуют проблемы с конструктором, см. Сообщение в блоге: http://bethmassi.blogspot.com/2006/01/serializing-data-across-time-zones-in.html, сообщение об ошибке: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=96118

0 голосов
/ 03 апреля 2015

После долгих лет борьбы с одной и той же проблемой я, наконец, решил создать решение для Поддержка часовых поясов SQL Server . В проекте используются стандартные часовые пояса IANA , перечисленные здесь .

Например:

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')

Я понимаю, что это не точно , что было задано, но я думаю, что это решит проблему одинаково хорошо.

0 голосов
/ 22 августа 2009

Вы проверяли эту статью на Channel9? Кажется, вы делаете то, что ищете в функции CLR ... хотя я не думаю, что вы получите ВСЕ вкусности, к которым хотите получить доступ ... но это только начало.

http://channel9.msdn.com/playground/Sandbox/139123/

Проблема, о которой упоминает один из авторов этого потока, заключается в том, что это небезопасная сборка из-за вызова p /.

0 голосов
/ 05 марта 2009

Мы искали это некоторое время, но не смогли найти хороший способ сделать это. Я думаю, что это было в списке вещей, которые будут добавлены в SQL 2008, если я помню, как смотрел это некоторое время назад.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...