13

マルチスレッド プロセスのログを DB に保存しようとしていますが、次のエラーが発生します。セッションで他のスレッドが実行されているため、新しいトランザクションは許可されません。

各トレッドには、次の機能があります。

 internal bool WriteTrace(IResult result, string message, byte type)
    {
        SPC_SENDING_TRACE trace = new SPC_SENDING_TRACE(
                        message,
                        Parent.currentLine.CD_LINE,
                        type,
                        Parent.currentUser.FULLNAME,
                        Parent.guid);
        Context.SPC_SENDING_TRACE.AddObject(trace);
        if (Context.SaveChanges(result) == false)
            return false;
        return true;

    }

Context はスレッドごとに異なりますが、DB との接続は常に同じです。

この問題を解決する方法はありますか?

ありがとうアンドレア

4

2 に答える 2

41

各トランザクションのコンテキストを作成してから破棄する必要があります。次のように実行できます。

using(var ctx = new MyContext()) {
    //do transaction here
}

閉じ括弧の後、コンテキストが破棄されます。

理解を深めるために、この投稿を参照してください。ken2kによる優れた回答が見つかります。問題を解決できることを願っています:)

アップデート:

.ToList()また、すべての LINQ クエリに追加してみてください。LINQ の結果を反復処理する場合、反復処理が完了するまで変更を加えることはできません。そのようなものがあるかどうかを確認するか、より多くのコード、つまり を呼び出すコードを共有してくださいWriteTrace。今回はこれが実際に役立つことを願っています。

于 2013-03-12T14:29:13.077 に答える
0

マルチスレッド環境でエンティティ フレームワークを使用します。この環境では、任意のスレッド、UI、およびバックグラウンド (STA と MTA の両方) が同じデータベースを同時に更新できます。新しいバックグラウンド スレッドでの使用開始時にエンティティ接続を最初から再作成することで、この問題を解決しました。エンティティ接続インスタンス ConnectionString を調べると、一般的な接続インスタンスをリンクするために使用されると思われるリーダー GUID が表示されます。エンティティ接続を最初から再作成することにより、GUID 値はスレッドごとに異なり、競合は発生していないように見えます。

// Build the connection string.

  var sqlBuilder = new SqlConnectionStringBuilder();
  sqlBuilder.DataSource = serverName;
  sqlBuilder.InitialCatalog = databaseName;
  sqlBuilder.MultipleActiveResultSets = true;
  ...
  var providerString = sqlBuilder.ToString();
  var sqlConnection = new SqlConnection(providerString);

// Build the emtity connection.

  Assembly metadataAssembly = Assembly.GetExecutingAssembly();
  Assembly[] metadataAssemblies = { metadataAssembly };
  var metadataBase = @"res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl";
  var dbModelMetadata = String.Format(metadataBase, objectContextTypeModelName);
  // eg: "res://*/Models.MyDatabaseModel.csdl|res://*/Models.MyDatabaseModel.ssdl|res://*/Models.MyDatabaseModel.msl"
  var modelMetadataPaths = modelMetadata.Split('|');
  var metadataWorkspace = new MetadataWorkspace(modelMetadataPaths, metadataAssemblies);
  var entityDbConnection = new EntityConnection(metadataWorkspace, sqlConnection);
  return entityDbConnection;
于 2016-02-17T00:07:07.707 に答える