5

私のセットアップ: ユーザーには、いくつかのアクションとデータ変換を実行するページがあります。
これらのアクションをデータセット (セッション内) に保存します。
次に、ボタンをクリックすると、さらに変換を実行し、各データテーブルの各行をデータベースに挿入するカスタム データベース関数を呼び出す必要があります。私はすべてうまくいきました、そしてそれはかなりうまくいきます。

ただし、ここで行う必要があるのは、ボタン クリック イベントをすぐに実行しないように変更することですが、そのアクションをキューに入れます (これはすべてのユーザーに共通のキューです)。したがって、user1 がボタンをクリックし、次に user2 がボタンをクリックした場合、user1 データセットを取得してメソッドを実行する必要があります。その後、user2 データセットを取得してメソッドを実行する必要があります。すべてのための 1 つのキュー。

private void btnclick()
{
  DataSet ds = Session["test"] as DataSet;
  PerformFinalTransformation(ds);
  foreach (DataTable dt in ds.Tables)
  {
     foreach (DataRow dr in dt.Rows)
     {
        CallCustomSqlFunction(dr);
     }
  }
}

データセットはユーザーごとに同じではないため(テーブル/列の数)、可能であればデータベースにデータセットを保存することは避けたいと思います。asp.net /c# でこれを行う方法についての指針を探しています。(quartz.net は考慮すべきものですか?)。どのような概念を探す必要がありますか? 並列プログラミング? またはasp.netキュー?または、他の何か?何から始めればよいのかわからないため、開始することさえできません。ところで、それが何らかの形で役立つ場合は、アプリで最新の DotNetNuke を使用します。

4

7 に答える 7

2

アーキテクチャの観点から、ソリューションは優れています。キューは行く方法です。ただし、解決策は簡単ではありません。考慮すべきいくつかの事柄:

  1. 復元力:システムがクラッシュまたは再起動した場合はどうなりますか?キューは保持されますか?
  2. このキューからどのように消費しますか?ASP.Netアプリケーションのスレッド(醜い)?Windowsサービス?
  3. 並行性についてはどうですか?

あなたの答えに応じて、私はあなたにいくつかの選択肢を与えます:

  1. [ConcurrentQueue][1]スレッドで上昇する、を使用したメモリ内のキュー。おそらくシングルトンを使用してキューへのアクセスを有効にします。私はあなたにこれをするように忠告しません。

  2. サービスを作成し、WCFを介してインターフェイスを公開し、ASP.Netアプリケーションからアクセスします。[ConcurrentQueue][2]サービスも同様に保持する必要があり、データベースなどにアクセスするのはサービスの責任になります(クラッシュやデータ損失の問題は引き続き発生します)。

  3. MSMQを使用します。また、ASP.Netからの呼び出しを受信し(ASP.NetにMSMQに直接アクセスさせたくない場合)、データベースにアクセスする(MSMQがこのサービスを呼び出す)機能をカプセル化する一部のサービス。

これらは私の頭のてっぺんからです。コメントしてください、そして私はできる限り答えます(私は現在働いています)。

于 2012-07-30T20:57:37.430 に答える
2
  1. 再起動後も存続するには、キューをデータベースに保存する必要があります。各データセットを xml にシリアル化し、結果の xml をnvarchar(max)列に格納することで、データの相違を克服できます。

  2. キューを実行する最善の方法は、一度に 1 つのアイテムを選択して処理する個別の Windows サービスを使用することです。IIS で同じことを行うことができます (単に で別のスレッドを開始するだけですApplication_Start) が、スケーリングできない (そして IIS の再起動、プールのリサイクルなどの影響を受ける) ため、お勧めしません。

于 2012-07-30T20:49:10.200 に答える
0

このような問題について私が持っている知識はほとんどありませんが、WCFとMSMQは、シナリオで間違いなく役立つ可能性のある優れたソリューションです。そして、あなたがそれをうまくやれば、あなたが望むもののデータベース実装を書くことは本当に悪いことではありません。AutoIncrement各挿入後にフィールドをに設定して、データベースにデータを追加するだけで済みます。

ただし、キューを使用してこの問題を解決するために、以下にいくつかのガイドとサンプルを示します。

プロジェクトの実装例:

それらがお役に立てば幸いです。幸運を。

于 2012-07-30T20:58:13.420 に答える
0

私がこれを行うことになっていた場合、おそらく次の方法で行うことになります。

キュー ストレージ

キューをメモリに保持したくない場合(これは悪い考えです。他の回答を参照してください)、サーバーのリセット時にクリアされないデータベースまたはその他のストレージがサーバー上にある必要があります。それ。もちろん、SQL Server のような従来のデータベースを使用することもできますが、他のオプションも利用できます。

サーバー上に SQL Server または同様の商用データベースがまだない場合は、RavenDB のようなドキュメント データベースを使用することをお勧めします。ファイル名のランダム性を考慮して、同じタイムスタンプを持つ 2 つのファイルを取得しないようにします (これはほとんどありませんが、発生します)。どちらのシナリオにも問題はありますが、完全な解決策はないと思いますので、ユーザーがサービスを使用する頻度に依存します。

キューを空にする

使用するキュー用のストレージの種類に応じて、サーバー上で 5 分ごとに実行されるスケジュールされたタスクとしてコンソール アプリケーションをセットアップするか、実行する必要がある頻度を設定します。スケジュールされたタスクは、キューに新しいジョブがあるかどうかを確認し、一番上のジョブを処理し続けます。

結論

上記の説明は、それを行う「簡単な」方法です。多くのスキルは必要ありませんし、まったく新しい種類のフレームワークなどに慣れる必要もありません。

実装とテストが非常に簡単なため、ファイルとスケジュールされたタスクを使用したソリューションを使用します。また、大量のトラフィックが発生した場合は、キューを格納する方法をパフォーマンスに適した方法にいつでも変更できます。

最後の注意点: デバッグに役立つように、キューからジョブを処理するたびにログを記録することを忘れないでください ;)

于 2012-07-30T21:51:02.653 に答える
0

並列ライブラリの「タスク」を見てみるといいと思います...

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

asinc キューを処理するのはとても良いことです。

データの損失を避けるために、ある種の永続性を使用することをお勧めしますが、データベースの別のテーブルに置くか、ファイルにシリアル化するか、その他の方法で行います。

メモリ ストレージだけを信頼するべきではありません。IIS のリセットまたは Windows の再起動、さらには appPool でのリサイクルによって、処理されていないデータが破壊されます。

于 2012-08-06T18:16:15.257 に答える
0

各行に対して関数を呼び出してデータベースに挿入するのではなく、テーブル値パラメーターを使用してデータを送信できますか? これは SQL Server 2008 以降の機能で、1 つのステートメントでテーブルを完全に送信できます。

この種のソリューションでは、キューは必要ない場合があります。テーブル パラメーターに切り替えると、コードのパフォーマンスが大幅に向上したため、ステートメントをバッチ処理する必要がないことがわかりました。

コードがどのように機能するかは次のとおりです。

private void btnclick()
{
    DataSet ds = Session["test"] as DataSet;
    PerformFinalTransformation(ds);
    using (SqlConnection conn = new SqlConnection(my_connection_string)) {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand("insert_multiple_tables", conn)) {
            cmd.CommandType = CommandType.StoredProcedure;
            SqlParameter param = new SqlParameter("@table0", SqlDbType.Structured);
            param.Value = ds.Tables[0];
            cmd.Parameters.Add(param);
            SqlParameter param = new SqlParameter("@table1", SqlDbType.Structured);
            param.Value = ds.Tables[1];
            cmd.Parameters.Add(param);
            cmd.ExecuteNonQuery();
        }
    }
}

次に、ストアド プロシージャを次のように定義できます。

CREATE TYPE udt_mytable0 AS TABLE (
    col1 int,
    col2 varchar(255),
    col3 datetime,
    -- and so on
)

CREATE TYPE udt_mytable1 AS TABLE (
    col1 bigint
)

CREATE PROCEDURE insert_multiple_tables
    @mytable0 udt_mytable0 READONLY,
    @mytable1 udt_mytable1 READONLY
AS

INSERT INTO mydatabase0
    (col1, col2, col3)
SELECT 
    col1, col2, col3
FROM 
    @mytable0

INSERT INTO mydatabase1
    (col1)
SELECT 
    col1
FROM 
    @mytable1
于 2012-07-30T21:05:09.360 に答える
-1

cacheを使用することでこれを実現できると思います。各セッションのデータを持つキューを作成し、キューをキャッシュに保存します。次に、キャッシュを使用してカスタム データベース操作を実行します。キューを使用しているため、FCFS になります。したがって、ユーザー 2 のデータは、ユーザー 1 のデータが使用された後にのみ使用されます。

于 2012-07-26T08:43:14.973 に答える