0

私の知る限り、MSDTC が関与するのは次の場合のみです。

  • 別のサーバーにリンクされているトランザクション内でビュー/テーブルをクエリしています。

  • 単一の TransactionScope 内で 2 つの SqlConnections (または NHibernate が使用するもの) を使用している

  • TransactionScope 内に別のトランザクション コンポーネント (MSMQ やトランザクション ファイル システムなど) を登録しています。

  • 言及されていない他の状況。

MSDTC を無効にして次のコードを実行すると、(サーバー 'サーバー' 上の MSDTC は利用できません) エラーが発生します。

public bool Add(PurchaseOrderInfo purchaseOrderInfo)
{
    using (TransactionScope ts = new TransactionScope())
    {
        using (SqlConnection Cnn = new SqlConnection(SqlHelper.ConnStr))
        {
            Cnn.Open();

                try
                {
                    using (SqlDataReader rdr = SqlHelper.ExecuteReader(/*Tr*/Cnn, "spPurchaseOrderAdd", purchaseOrderInfo.ExpectedShipment.ShipmentID, purchaseOrderInfo.CreateDate, purchaseOrderInfo.CustomerNotes, purchaseOrderInfo.Status, purchaseOrderInfo.PurchaseOrderNumber))
                    {
                        if (rdr.Read())
                            FillPurchaseOrderInfo(rdr, ref purchaseOrderInfo, GettingDepthEnum.Level_0);
                        else
                        {
                            return false;
                        }
                    }

                    foreach (PurchaseOrderDetailInfo detailInfo in purchaseOrderInfo.Details)
                    {
                        throw new Exception("Test");
                        //if (!AddPurchaseOrderDetail(Tr, purchaseOrderInfo, detailInfo))
                        {
                            //Tr.Rollback();
                            return false;
                        }
                    }

                    return true;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                ts.Complete();
            }
        }
    }

何か不足していますか?

更新: ストアド プロシージャには、単純な挿入ステートメントが含まれています。

INSERT INTO tblPurchaseOrder
(ShipmentID, CreateDate, CustomerNotes, PurchaseOrderState, PurchaseOrderNumber, LastActivityDate)
VALUES
(@ShipmentID, @CreateDate, @CustomerNotes, @PurchaseOrderState, @PurchaseOrderNumber, GETDATE());

--Step 2: return row that INSERTED to Client Computer.
SELECT dbo.viwGetPurchaseOrderWeight.Weight,* FROM tblPurchaseOrder LEFT OUTER JOIN viwGetPurchaseOrderWeight ON viwGetPurchaseOrderWeight.PurchaseOrderID =  tblPurchaseOrder.PurchaseOrderID WHERE (tblPurchaseOrder.PurchaseOrderID = Scope_Identity());

UPDATE2: MSDTC をシャットダウンすると、実行が次の行に到達したときに例外がスローされます。

using (SqlDataReader rdr = SqlHelper.ExecuteReader(/*Tr*/Cnn, "spPurchaseOrderAdd", purchaseOrderInfo.ExpectedShipment.ShipmentID, purchaseOrderInfo.CreateDate, purchaseOrderInfo.CustomerNotes, purchaseOrderInfo.Status, purchaseOrderInfo.PurchaseOrderNumber))

つまり、後続の行は効果がありません。

4

4 に答える 4

2

接続を再度開かないようにしてください。

using (TransactionScope transactionScope = new TransactionScope()) {
    using (SqlConnection connection = new SqlConnection(connectionString)) {
    connection.Open();
    connection.Close();
    connection.Open(); // escalates to DTC
      }
}
于 2013-04-23T20:57:57.923 に答える
1

スタック トレースを使用した投稿によると、EntLib クラスが別の接続を開いています。トランザクションから除外する必要があります。ExecuteReader呼び出しを抑制トランザクション スコープにラップします。

SqlDataReader rdr;
using (var tsSuppress = new TransactionScope(TransactionScopeOption.Suppress))
    rdr = SqlHelper.ExecuteReader(...)

これは一時的Transaction.Currentに null に設定されるため、新しい接続はトランザクションを取得しません。

補足として、スタック トレースにより、問題の根本原因を見つけることができました。

于 2013-04-24T11:58:34.800 に答える
0

コードを調べると、パラメーター値だけでなくインスタンスを取るSQLHelperオーバーロードを使用すると、どのパラメーターがどの値にマップされているかを把握しようとするステップが節約され、2 回目のトリップが節約されます。データベースと 2 番目の接続、および MSDTC へのトランザクションの昇格。ExecuteReaderSqlParameterSQLHelper

私が見ているコードによると、これはおそらくあなたが呼び出すべきメソッドです:

Public Overloads Shared Function ExecuteReader(ByVal connectionString As String, _
                 ByVal commandType As CommandType, _
                 ByVal commandText As String, _
                 ByVal ParamArray commandParameters() As SqlParameter) As SqlDataReader

それでもうまくいかない場合は、独自の DAL を作成することをお勧めします。:)

お役に立てれば。

于 2013-04-24T12:09:02.080 に答える