2017-07-12 3 views
3

SQLのデータベースにいくつかの.net関数を公開している古いソリューションに立ち向かっています。しかし、新しいデータベースに公開しようとする試みは、日付を操作する関数では失敗しています。SQL CLRデータベースを公開しようとする日時型の不一致

失敗の機能は次のとおりです。

[SqlFunction(TableDefinition="localtime datetime2", IsDeterministic=true, IsPrecise=true, 
      DataAccess=DataAccessKind.None, 
      SystemDataAccess=SystemDataAccessKind.None)] 
public static DateTime ConvertFromUTC(DateTime utctime, string timezoneid) 
{ 
    if (utctime.Kind == DateTimeKind.Unspecified) 
     utctime = DateTime.SpecifyKind(utctime, DateTimeKind.Utc); 

    utctime = utctime.ToUniversalTime(); 

    return TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utctime, timezoneid); 
} 

公開しようとしたときに、私が取得エラーメッセージは次のとおりです。

[DBO]の作成[ConvertFromUTC] ...

( 268,1):SQL72014:.Net SqlClientデータプロバイダ:

メッセージ6551、レベル16、状態2、手順ConvertFromUTC、行1
戻り値のT-SQL型とCLR型が一致しないため、「ConvertFromUTC」のCREATE FUNCTIONが失敗しました。

(268,0):機能のバージョンの

CREATE FUNCTION [dbo].[ConvertFromUTC] 
    (@utctime DATETIME, @timezoneid NVARCHAR (MAX)) 
RETURNS TABLE ([localtime] DATETIME2 (7) NULL) 
AS EXTERNAL NAME [database].[IntelligentTutor.Database.Functions].[ConvertFromUTC] 

SQL定義:SQL72045:機能を追加するための試みで、.NETから生成されたスクリプトの実行エラー

SQL

CREATE FUNCTION [dbo].[ConvertFromUTC] 
    (@utctime [datetime], @timezoneid [nvarchar](4000)) 
RETURNS [datetime] WITH EXECUTE AS CALLER 
AS EXTERNAL NAME [database].[IntelligentTutor.Database.Functions].[ConvertFromUTC] 
+0

@ Mattの回答に記載されている提案に加えて、次の点も考慮する必要があります。属性から 'TableDefinition =" localtime datetime2 "、'を削除してください。 'timezoneid'に' string'の代わりに 'SqlString'を使います(' return'の 'timezoneid'を' timezoneid.Value'に変更する必要があります)。 '@timezoneid'を' NVARCHAR(MAX) 'からNVARCHAR(50)に変更するか、または' MAX'ではないサイズに変更してください。また、 'TimeZoneInfo'クラスにメモリリークがあることに注意してください。なぜなら、アセンブリに' UNSAFE'とマークする必要があるからです。 –

+0

一般的なSQLCLRの使用の詳細については、SQL Server Centralの[Stairway To SQLCLR](http://www.sqlservercentral.com/stairway/105855/)(無料登録彼らのコンテンツを読む必要がありますが、それは価値があります)。 –

+0

@srutzky - ['HostProtectionAttribute.MayLeakOnAbort'](https://msdn.microsoft.com/en-us/library/system.security.permissions.hostprotectionattribute.mayleakonabort.aspx)は、「メモリリークがある」という意味ではありません。 –

答えて

3

SQL functi:既存のデータベース(@MattJohnsonは、それが一定の必要方法については正しかったことを確認した)でonは.NETメソッドのシグネチャと一致しません。それが一致するようにするには:

  1. DATETIME2の代わりに、関数定義のDATETIME@utctimeのあなたのタイプを変更し

  2. NULL可能なdatetime2列を持つテーブルを返す代わりに、戻り値の型をちょうどRETURNS DATETIME2に変更します。

また、あなたはSQL 2016で以降、またはAzureのSQL DB上にある場合、あなたは今、代わりにAT TIME ZONEを使用することができるよう、あなたは、この機能を必要としないことに注意してください。

+0

私は考えることができる前に、既存のサイトを稼働させる必要があります(私が得たのは、明らかにウェブサーバーとDBダンプをコピーしたコードのスナップショットでした。これにスキップされたコードの近代化を12年以上かけて適用し始めました。私が現在持っているものは、古い方の.net/sqlサーバーのペアで動作していますか?あるいは、ウサギの穴にさらに深く登って何が起こっているのか把握する必要がありますか? –

+0

@DanNeely質問に投稿したコードがこれまでに働いていたということはありません。テーブルを返す唯一の方法は、.NETの戻り値の型が 'IEnumerable'であるかどうかです。また、 'SqlFunction'属性にFillRowMethodが書かれていなくても、テーブルを返すことはできません。これは、この答えでMattが言及した2つの項目に加えてあります(これは完全に正しいです、btw、+1)。 –

+0

.netコードが単一の値を返し、SQLラッパーがテーブルを要求するため、これはうまくいかないでしょう。スカラー値関数はテーブル値関数とは異なります。 [こちらを読む](https://docs.microsoft.com/en-us/sql/relational-databases/clr-integration-database-objects-user-defined-functions/clr-user-defined-functions) –