web-dev-qa-db-ja.com

SQL Server CLR関数のSystem.Web

私はこのトピックについていくつかの簡単な調査を行いましたが、SQL Server内でこの特定の.dllを有効または登録することについて、すべての長所と短所を知りたいのですが?

戻る情報-残念ながら、この.dllを必要とするサードパーティ製アプリケーション(私の決定ではありません)と統合しています。 CLR関数に必要なのは、SSMSでSQLクエリを記述し、そのデータをサードパーティのアプリケーションのAPIに送信して、適切なデータのロード/変更(このアプリケーションへの挿入とこのアプリケーションからの削除)を実行することです。 APIを介して実行されます)。

編集-多分私はこの詳細を含めるべきだった

私のc#クラスを登録しようとしたときに、「system.web not registered blah blah blah blah」というエラーが表示されたため、このトピックに関する調査が行われました。

編集を終了

したがって、私の難問は、C#クラス/.dllを登録できるようにするために、依存するすべての.dllを登録する必要があるということですが、私の調査に基づいて、この特定のDLLはかなり問題になる可能性があることがわかっています。

私のグーグル調査以外の落とし穴に私がどのように精通していないかを見て、私はあなたのすばらしい人の一人がこれに関して最良の決定をする方法を理解するのを手伝ってくれるだろうかと思っていました。

また、洞察を与えることが容易になるように、この投稿に他に何を追加できますか? C#コードが適切であることを確信していませんか?これは少し広いかもしれないと理解していますが、フラグが立てられないように十分に具体的であることを望んでいましたか?

ここで発生していることをより具体的に(ソロモンの要求による)

  1. サードパーティのアプリは「API」(私はそれが素晴らしいAPIではないと言われているので大まかに使用されます)を使用してデータを送受信します。変換するデータテーブルまたはExcelファイルのみを取得するインポーター関数を呼び出すことに気づくでしょう。会社が通常のXMLを介した挿入と削除はひどく遅く、予期しない動作があると私に言ったので、私には他に選択肢はありません。

  2. System.Webを参照する.DLLは、C#クラス内で参照されます。これは、最初にデータを送信できるようにするために必要です。

  3. に関してで:

    前述の方法を使用できないのはなぜですか?それらはSQL ServerのCLRホストに既に存在します。これはWebサービス用です

これに答えるのに一般的なAPIについて十分に知っているかどうかはわかりません。私にはそうするための知識と経験がまったくなかったでしょう。また、この特定のAPIを操作する方法に制限があり、これらの制限がこれらのメソッドにどのように適用されるのかわかりません。 (私はさらに調査し、この質問に自分で答えられるかどうかを確認します)。

考えれば考えるほど、SQL Serverが呼び出すことのできる「中間者」クラスを作成し、別のクラスを呼び出すことができます。このクラスは、すべての正しい参照を持ち、現在の状況を乗り越えてしまう可能性があります。しかし、私はまだ特定のフィードバックに興味があるので、これから学ぶことができます。

これが私のc#クラスです:

    using Perfion.Api;   -- this .DLL references System.Web. 
    using Perfion.Api.Import;
    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;

    namespace PerfInsert
    {
        public static class PerfionInsert 
        {
            public static bool CreateCommand(string tblString, string featureName, string connectionString, string perfionConnectionString, string logFile)
            {
                StringBuilder logInfo = new StringBuilder();
                try
                {
                    var wList = new Regex(@"[^0-9a-z\.\[\]_]#", RegexOptions.IgnoreCase);
                    if (wList.IsMatch(tblString))
                    {
                        logInfo.AppendLine($"{DateTime.UtcNow} - Regex Validation Failed for Table Name!");
                        return false;
                    }
                    using (SqlConnection connection = new SqlConnection(connectionString))
                    {
                        var qryString = "SELECT * FROM " + tblString;
                        using (SqlCommand command = new SqlCommand(qryString, connection))
                        {
                            connection.Open();
                            using (var dataReader = command.ExecuteReader())
                            using (var dataTable = new DataTable())
                            {
                                dataTable.Load(dataReader);
                                PerfionApi api = new PerfionApi(perfionConnectionString);
                                Importer importer = new Importer(api.Connection);
                                importer.Status += (sender, e) => { logInfo.AppendLine($"{DateTime.UtcNow} - {e.Title}"); };
                                importer.LoadData(dataTable);
                                importer.ImportToDatabase(featureName);
                            }
                        }
                    }
                    return true;
                }
                catch (Exception ex)
                {
                    logInfo.AppendLine($"{DateTime.UtcNow} - {ex.ToString()}");
                }
                finally
                {
                    File.AppendAllText(logFile, logInfo.ToString());
                }
                return false;
            }
        }
    }
5
Doug Coats

サードパーティのソフトウェアがDLL=を必要とすることは、ここでは関連がないようです。問題は単に次のように見えます:

SSMSでSQLクエリを記述し、そのデータをサードパーティのアプリケーションのAPIに送信できるようにする必要があります。次に、このAPIが正しいデータのロード/変更(このアプリケーションへの挿入とこのアプリケーションからの削除)を実行する必要があります。そのAPIを介して行われます)。

私はあなたの最良の2つのオプションは次のとおりです。

  1. このプロセスがあなたが述べたように単純で、本当にSystem.Webを使い続けたい場合は、クエリを実行し、必要なものをAPIにポストするコンソールアプリケーションを作成してみませんか?これを定期的に実行する必要がある場合は、WindowsタスクスケジューラまたはSQL Serverエージェント( "オペレーティングシステム(CmdExec)"ジョブステップ経由)でスケジュールできます。
  2. このプロセスがもう少し複雑な場合、および/またはこれらのクエリをより動的/アドホックな方法で実行する機能が必要な場合、System.Web必須ではありません、一部のコーディングが簡単になるだけです。代わりに、 HttpWebRequest および HttpWebResponse を調べてください。これら2つは、SQLCLRでサポートされている.NET Frameworkライブラリの1つであるSystem.Netに含まれています。主な違いは、XMLリクエストを手動で作成する必要があることです。応答の処理についても同様です。この方法は、System.Webをインポートするよりも安定していて安全です。

    これらの線に沿って、そのような機能を必要とするがコーディングをしたくない(またはできない)だれでも、ストアドプロシージャを含むSQLCLR関数とプロシージャのライブラリを作成しました— SQL#INET_GetWebPages、これらの2つのメソッドを実装します。無料バージョンがありますが、この特定のストアドプロシージャは、フル(有料)バージョンでのみ使用できます。ただし、さまざまなHTTPヘッダーの設定、オプションの基本認証、プロキシサーバー、GETの送信とPOSTデータ、PUTリクエストの処理、および削減のためのオプションを含む、さまざまなオプション/シナリオを処理しますパフォーマンスへの潜在的な悪影響。

サードパーティアプリのDLLを使用して、提供されたメソッドを介してAPI呼び出しを行うと言っている場合、それらが参照し、使用するのはDLLです。 System.Web(コードを直接ではなく)では、すべての影響を完全に確実に述べることは困難ですが、このアプローチに関して考慮すべき点がいくつかあります。

System.Webは、SQLCLRの サポートされている.NET Frameworkライブラリ リストにありません。つまり、少なくとも:

  1. このライブラリは、SQL Serverでの読み込みが保証されていません。現在ロードできる場合でも、SQL Serverは純粋なMSILライブラリのみを許可し、混合モードライブラリ(つまり、マネージコードとアンマネージコードの両方を含むDLL)をロードしません。この制限を回避する方法はありません。このライブラリはリストにないため、 can は、将来の.NET Frameworkの更新で純粋から混合に変更できます。これが発生した場合、これはフレームワークライブラリであり、GACに読み込まれるため、このコードは機能を停止します。SQLServerとGACの両方に読み込まれるライブラリは、まったく同じバージョンである必要があります(そのため、古い機能バージョンを引き続き使用することはできません) 。この純粋から混合への変更は頻繁には起こりませんが、以前に起こりました。
  2. このライブラリはUNSAFEとしてロードする必要があります。これは本質的に問題ではありませんが、簡単に問題になる可能性のある動作は可能です。たとえば、このサードパーティで使用されているコードパスのいずれかである場合DLL情報をキャッシュするために静的変数を使用します。その値が標準ではない場合(つまり、値が変更されたり、変更されたりする可能性があります)このコードの呼び出し)、SQL Serverは共有アプリドメインを使用し、 all セッションは同じメモリ/静的データを共有するため、競合状態になる可能性があります。

「サポート対象」リストにないため、UNSAFEとしてロードする必要のあるコードがいくつかあり、特定のコードパスを使用しない場合でも、セキュリティポリシーに違反するコードが含まれています。このような場合、コードは technically "SAFE"のようになりますが、ソースコードを確認しないと、確実に判断できません。したがって、テストする必要がありますが、テストでは複数の人が数回クリックする必要があります。競合状態が存在するかどうかを確認するには、このコードにアクセスする複数の同時セッションが必要です。ただし、例外によるメモリリークなど、さらにテストが難しいシナリオもあります。このため、サポートされているライブラリの一部のメソッドは制限されていますが、サポートされていないライブラリのメソッドにそのような問題があるかどうかは、テストされたとは思えないため、おそらく誰にもわかりません。

この機能がユーザー向けではないことを意図している場合(つまり、システムプロセス、社内の機能など)、問題(セキュリティ、パフォーマンス、安定性)の most を軽減できます。 SQL Server Expressのインスタンスを起動し、そこにプロジェクトをロードします。これにより、理想的でないSQLCLR機能が本番アプリケーションから分離/隔離されます。すでに通常の外部SqlConnection(内部/信頼された接続ではない)を使用していると仮定すると、コードを変更する必要はありません。

このアプローチで軽減できない唯一のリスク(つまり、SQLCLRプロジェクトを分離されたインスタンスにロードすること)は、MicrosoftがSystem.Web(またはそれをロードするときに吸い込まれる依存関係のいずれか)を更新すると、コードが壊れる可能性があります。 SQL Serverへ)を混合モードライブラリに変更します。それが起こることは決してないかもしれませんが、その場合、サードパーティをロードすることはできませんDLL彼らがHttpWebRequestを使用するように切り替えない限り、彼らはする理由がほとんどありませんそのような変更を行います。

更新

O.P.関連する質問に回答して、プロジェクトタイプをコンソールアプリに変更することを選択し、SQL Agentでスケジュールする可能性が最も高い(ただし、Windowsタスクスケジューラを使用することもできる)

関連投稿(StackOverflow)]

  1. SQLCLRストアドプロシージャの場合、CREATE PROCEDUREは「メッセージ6567、レベル16、状態2」を取得します
  2. CLR関数を使用したSystem.Security.SecurityException
7
Solomon Rutzky