簡體   English   中英

錯誤 - 具有多個數據庫連接的LINQ / TransactionScope

[英]Error - LINQ/TransactionScope with multiple database connections

我有一個helluva時間將幾個事務包裝到同一個SQL Server上的兩個不同的數據庫。 我最初遇到網絡DTC訪問問題,我解決了這個問題。 現在,我繼續得到的錯誤是“與底層事務管理器的通信失敗了”。

我們在數據庫中有一些客戶配置文件,當這些配置文件過時時,我們希望將它們移動到“存檔”數據庫進行存儲。 此舉簡單(幽默斜體)將它們添加到存檔數據庫並從主/實時數據庫中刪除它們。 我為每個數據庫都有一個DataContext。 下面的代碼執行Add,然后在嘗試使用第二個DataContext時獲取Delete上的錯誤。 我只和LINQ合作了幾個月,過去幾天我一直在搜索文章。 我想知道我的代碼是否有任何問題,或者是否仍有未正確配置的DTC或???

我們在VMware上運行我的工作站和服務器。 - Workstation是Windows 7 SP1 - 服務器是Windows和SQL Server 2008R2

“移動”的常規:

private int MoveProfileToArchiveDB( int iProfileId )
{
    int rc = RC.UnknownError;

    // get new Archive profile object
    ProfileArchive.ProfileInfo piArchive = new ProfileArchive.ProfileInfo();

    // 'Live' DataContext
    using ( ProfileDataContext dbLive = new ProfileDataContext() )
    {
        // get Live profile
        ProfileInfo piLive = ProfileInfo.GetProfile( dbLive, iProfileId );

        // copy Live data to Archive profile object... including the id
        ProfileArchive.ProfileInfo.CopyFromLive( piLive, piArchive, true );
    }

    bool bArchiveProfileExists = ProfileArchive.ProfileInfo.ProfileExists( piArchive.id );

    // make the move a transaction... 
    using ( TransactionScope ts = new TransactionScope() )
    {
        // Add/Update to Archive db
        using ( ProfileArchiveDataContext dbArchive = new ProfileArchiveDataContext() )
        {
            // if this profile already exists in the Archive db...
            if ( bArchiveProfileExists )
            {
                // update the personal profile in Archive db
                rc = ProfileArchive.ProfileInfo.UpdateProfile( dbArchive, piArchive );
            }
            else
            {
                // add this personal profile to the archive db
                int iArchiveId = 0;
                piArchive.ArchiveDate = DateTime.Now;
                rc = ProfileArchive.ProfileInfo.AddProfile( dbArchive, piArchive, ref iArchiveId );
            }

            // if Add/Update was successful...
            if ( rc == RC.Success )
            {
                // Delete from the Live db
                using ( ProfileDataContext dbLive = new ProfileDataContext() )
                {
                    // delete the personal profile from the Profile DB
                    rc = ProfileInfo.DeleteProfileExecCmd( dbLive, iProfileId );    // *** ERROR HERE ***
                    if ( rc == RC.Success )
                    {
                        // Transaction End (completed)
                        ts.Complete();
                    }
                }
            }
        }

    }

    return rc;
}

筆記:

  1. 我有一些不同的刪除方法,它們都在TransactionScope之外工作。
  2. ProfileInfo是主要的配置文件表,對於Live和Archive數據庫大致相同。

任何幫助是極大的贊賞! 非常感謝...

我決定將此作為答案發布,而不是繼續交叉評論。

  • 不要使用錯誤代碼。 這就是例外情況。 代碼流更難以閱讀,錯誤代碼返回邀請被忽略。 例外使代碼更易於閱讀,並且更不容易出錯。

  • 如果使用TransactionScope,請記住始終明確設置隔離級別。 請參閱使用新的TransactionScope()認為有害 SERIALIZABLE的隱含隔離級別幾乎從未被要求,並且具有巨大的負面影響。

  • 交易升級。 每當在事務范圍內打開多個連接時,它們就可以將事務升級為分布式事務。 行為因版本而異,有些人試圖將其記錄下來,例如。 TransactionScope:事務升級行為

SQL Server 2008比SQL Server 2005更加智能,並且可以自動檢測特定事務中的所有數據庫連接是否指向同一物理數據庫。 如果是這種情況,則事務仍為本地事務,並且不會升級為分布式事務。 不幸的是有一些警告:

  • 如果嵌套了打開的數據庫連接,則事務仍會升級為分布式事務。
  • 如果在事務中,與另一個持久資源建立連接,則事務會立即升級為分布式事務。

由於您的連接(來自使用的兩個數據上下文)指向不同的數據庫,即使在SQL Server 2008上,您的TransactionScope也會升級到分布式事務。

將您的申請納入DTC至少有兩種方式:

  • 吞吐量將下降到最低點。 數據庫每秒可以支持幾千個本地事務,但每秒只能支持幾十(可能是幾百個)分布式事務。 這主要是因為兩階段提交的復雜性。
  • DTC需要協調員:MSDTC。 [對MSDTC進行的安全性增強]使配置更具挑戰性,開發人員發現在他們的應用程序中需要MSDTC,這當然是出乎意料的。 鏈接文章中描述的步驟可能就是您現在所缺少的 對於Windows Vista / Windows 7 / Windows Server 2008 / Windows Server 2008R2 ,Windows Vista和Windows Server 2008中的MSDTC如何在Windows 2008和其他類似文章中配置DTC中描述了這些步驟。

現在,如果你解決以下上面提到的文章,你的代碼應該是工作MSDTC通信,但我仍然相信這歸檔應該在客戶端運行的代碼EF發生。 有更好的工具, SSIS是一個很好的例子。 運行SSIS的夜間計划作業將更有效地傳輸這些未使用的配置文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM