2013-03-12 64 views
9

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

私はこの機能を持っている:

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; 

    } 

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

この問題を解決する方法はありますか?コンテキストが配置されているクローズドブラケット後

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

はあなたが各トランザクションのコンテキストを作成し、それを配置する必要があり、あなたはこのようにそれを行うことができますあなたの アンドレア

答えて

34

に感謝します。

this postを参照してください。偉大な回答はken2kです。あなたが発行する修正することを願って:)

UPDATE:

また、あなたは持っているすべてのLINQクエリに.ToList()を追加してみてください。 LINQの結果を反復処理するときは、反復処理が完了するまで変更を加えることはできません。そのようなことがあるかどうかを確認するか、コードを共有してください。具体的にはWriteTraceに電話してください。今回はこれが実際にあなたを助けてくれることを願っています。

+0

メインアプリケーション(マルチスレッドではありません)には別のコンテキストがありますが、マルチスレッドが実行されているときには書き込み中ではありません。それでも問題が発生する可能性はありますか? – andrea

+0

@andreaあなたの主なアプリケーションに別のコンテキストがない場合は、dbから何かをリクエスト、追加、削除、または更新する必要があるときにコンテキストを作成してみてください。 ** single ** transaction。それが修正されない場合は、 'context.SaveChanges()'に 'lock'を追加してください。それが助けてくれることを願っていますが、私は確かにそうは思いませんが、幸いです!とにかく返信してください;) – ecampver

+0

@andrea最後のコメントを忘れて、最初に私の答えを更新してください。 – ecampver

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; 
+0

答えの大部分をコピーして別の質問に貼り付けないでください。 – Andy

関連する問題