<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      happyhippy

      這個(gè)世界的問題在于聰明人充滿疑惑,而傻子們堅(jiān)信不疑。--羅素

          Linq to SQL支持三種事務(wù)處理模型:顯式本地事務(wù)、顯式可分發(fā)事務(wù)、隱式事務(wù)。(from  MSDN: 事務(wù) (LINQ to SQL))。MSDN中描述得相對(duì)比較粗狂,下面就結(jié)合實(shí)例來對(duì)此進(jìn)行闡述。

      0. 測(cè)試環(huán)境
      OS Windows Server 2008 Enterprise + sp1
      IDE Visual Studio 2008, .net framework 3.5 + SP1
      DB SQL Server 2000 + sp4
      SQL Server 2008 Enterprise Edition

       

      1. 隱式事務(wù)

          當(dāng)調(diào)用SubmitChanges 時(shí),L2S會(huì)檢查當(dāng)前環(huán)境是否開啟了事務(wù)(下面兩節(jié)中創(chuàng)建的事務(wù)),如果沒有開始事務(wù),則 L2S啟動(dòng)本地事務(wù)(IDbTransaction),并使用此事務(wù)執(zhí)行所生成的 SQL 命令。

          使用Reflector查看DataContext.SubmitChanges的源代碼(見本文最后的附錄),可以看到,如果開啟了一個(gè)事務(wù),并將其傳給DataContext.Transaction,則在執(zhí)行SubmitChanges時(shí)就不會(huì)再重新開啟一個(gè)新的事務(wù)了。

          例如,下面的代碼會(huì)創(chuàng)建應(yīng)隱式事務(wù):

         1: public static void TestTranIn2000()
         2: {
         3:     using (SQL2000.Sql2000DataContext context1 = new SQL2000.Sql2000DataContext())
         4:     {
         5:         List<SQL2000.TLINQ> linq = context1.TLINQ.ToList();
         6:         linq.ForEach(e => e.Value += e.Value);
         7:         context1.SubmitChanges();
         8:     }
         9: }

          可以打開SQL Server Profile來查看生成的T-SQL,生成的Update語句被包含在Begin Transaction和Commit Transaction之間,如下圖所示:

      L2S_SQL2000_Tran

          上圖是我使用Linq to SQL + SQL Server 2000進(jìn)行測(cè)試的結(jié)果。下圖是我用Linq to SQL + SQL Server 2008測(cè)試的結(jié)果:

      L2S_SQL2008_Tran

          很奇怪的是,居然沒有Begin Transaction和Commit Transaction了。Begin/commit trand的事件類型是“SQL:BatchStarting”/“SQL:BatchCompleted”,從這個(gè)圖中可以看到,我有跟蹤這個(gè)事件(譬如第一個(gè)框中的Select命令),汗……是MSDN上說錯(cuò)了?

          抱著這個(gè)疑問,我又針對(duì)Linq to Sql + SQL Server 2008做了進(jìn)一步測(cè)試(這個(gè)例子也可以用來測(cè)試后面兩節(jié)中的事務(wù)處理,確保所有操作被分封裝在同一個(gè)事務(wù)中。):

      L2S_TranInSQL20081

          這里里面做了兩件事:創(chuàng)建一個(gè)新對(duì)象,同時(shí)還修改原有記錄中的值。我故意Insert可以執(zhí)行成功,而讓Update語句執(zhí)行出錯(cuò);如果有啟用事務(wù),則出錯(cuò)后事務(wù)會(huì)回滾,最終不會(huì)創(chuàng)建新記錄;如果沒有啟用事務(wù),則可以正常插入,但不會(huì)執(zhí)行第二步中的更新。

          注意:從理論上講,執(zhí)行SubmitChanges時(shí),并不一定是按照上面代碼的順序,先執(zhí)行插入再執(zhí)行更新;下面是MSDN上的說法:

          當(dāng)您進(jìn)行此調(diào)用時(shí),DataContext 會(huì)設(shè)法將您所做的更改轉(zhuǎn)換為等效的 SQL 命令。您可以使用自己的自定義邏輯來重寫這些操作,但提交順序是由 DataContext 的一項(xiàng)稱作“更改處理器”的服務(wù)來協(xié)調(diào)的。事件的順序如下:

      1. 當(dāng)您調(diào)用 SubmitChanges 時(shí),LINQ to SQL 會(huì)檢查已知對(duì)象的集合以確定新實(shí)例是否已附加到它們。如果已附加,這些新實(shí)例將添加到被跟蹤對(duì)象的集合。

      2. 所有具有掛起更改的對(duì)象將按照它們之間的依賴關(guān)系排序成一個(gè)對(duì)象序列。如果一個(gè)對(duì)象的更改依賴于其他對(duì)象,則這個(gè)對(duì)象將排在其依賴項(xiàng)之后。

      3. 在即將傳輸任何實(shí)際更改時(shí),LINQ to SQL 會(huì)啟動(dòng)一個(gè)事務(wù)來封裝由各條命令組成的系列。

      4. 對(duì)對(duì)象的更改會(huì)逐個(gè)轉(zhuǎn)換為 SQL 命令,然后發(fā)送到服務(wù)器。

          此時(shí),如果數(shù)據(jù)庫檢測(cè)到任何錯(cuò)誤,都會(huì)造成提交進(jìn)程停止并引發(fā)異常。將回滾對(duì)數(shù)據(jù)庫的所有更改,就像未進(jìn)行過提交一樣。DataContext 仍具有所有更改的完整記錄。

          因此,這里還是打開SQL Server Profile來確認(rèn):
      L2S_TranInSQL20082

          OK,現(xiàn)在可以放心了,這里的確是先執(zhí)行Insert,再執(zhí)行Update;執(zhí)行Update時(shí)出現(xiàn)了SqlException異常。這時(shí)查看測(cè)試表TLINQ中的數(shù)據(jù),發(fā)現(xiàn)沒有插入新的記錄進(jìn)去。也就是說,這里使用了事務(wù),但是SQL Server Profile沒有跟蹤到
          至于為啥會(huì)這樣,我暫時(shí)也沒有搞清楚;還有就是下面一節(jié)中即使執(zhí)行DbConnection.BeginTransaction(),也不會(huì)跟蹤到begin tran和commit tran。不知道是不是SQL Server 2008里面升級(jí)了啥。哪位如果知道原因,麻煩告知我一聲,謝謝。

          最后總結(jié)一下隱式事務(wù)的優(yōu)缺點(diǎn):

          優(yōu)點(diǎn):使用簡單,L2S都幫我們搞定了,我們不需要寫任何代碼。

          缺點(diǎn):只能處理單個(gè)DataContext中的單個(gè)SubmitChanges()函數(shù)的調(diào)用。如果需要將SubmitChanges()與其他自定義更新操作(譬如ExcuteCommand)共用一個(gè)Transaction、或者與其他DataContext共用一個(gè)DBTransation,就沒轍了.......

       

      2. 顯式本地事務(wù)

          SubmitChanges只能處理最基本的CUD(Create/Update/Delete)操作;而在日常的應(yīng)用中,邏輯往往沒有這么簡單,或者考慮性能等因素,我們需要配合ADO.Net執(zhí)行原生的TSQL;這時(shí)我們可能要讓ADO.Net + Linq to SQL來進(jìn)行配合處理。

          也就是說,我們可以手工創(chuàng)建一個(gè)DbConnection和DbTransaction,然后傳給DataContext,代碼示例如下:

         1: public static void TestTranInSQL2008()
         2: {
         3:     using(SqlConnection conn = new SqlConnection(Settings.Default.AdventureWorksConnectionString))
         4:     {
         5:         conn.Open(); //1. 創(chuàng)建并打開DbConnection連接
         6:         using (SqlTransaction tran = conn.BeginTransaction()) //2. 開啟DbTransaction
         7:         {
         8:             //3. 使用ADO.Net執(zhí)行TSQL
         9:             SqlCommand cmd = new SqlCommand("Update TLinq SET Value=10", conn, tran);
        10:             cmd.ExecuteNonQuery();
        11:  
        12:             //4. 配合Ado.Net和Linq to Sql: 將ADO.Net的DbConnection和DbTransaction傳給Linq to Sql
        13:             using (AdventureWorksDataContext context1 = new AdventureWorksDataContext(conn))
        14:             {
        15:                 context1.Transaction = tran;
        16:                 List<TLINQ> linq = context1.TLINQ.ToList();
        17:                 context1.TLINQ.InsertOnSubmit(new TLINQ() { Value = "1" });
        18:                 linq.ForEach(e => e.Value = (Convert.ToInt32(e.Value) + 1).ToString());
        19:                 context1.SubmitChanges();
        20:             }
        21:  
        22:             tran.Commit(); //5. 需要提交手工創(chuàng)建的事務(wù)
        23:         }
        24:     }
        25: }

          最后總結(jié)一下使用顯式本地事務(wù)的優(yōu)缺點(diǎn):

          優(yōu)點(diǎn):可以配合Ado.Net一起使用,或者跨DataContext使用,實(shí)現(xiàn)負(fù)責(zé)的業(yè)務(wù)邏輯。

          缺點(diǎn):處理步驟比較繁瑣。L2S中的DataContext已經(jīng)提供了ExcuteCommand方法來執(zhí)行原生的TSQL,這里還這樣使用Ado.net就太折騰自己了.......

       

      3. 顯式可分發(fā)事務(wù)

          使用TransactionScope來進(jìn)行顯示可分發(fā)事務(wù)控制。TransactionScope就像事務(wù)處理里面的一面魔鏡,如果需要事務(wù),就對(duì)著它喊:“主啊,請(qǐng)賜我事務(wù)!”,于是這個(gè)操作就有了事務(wù)功能。關(guān)于TransactionScope的詳細(xì)介紹,可以參考MSDN:使用事務(wù)范圍實(shí)現(xiàn)隱式事務(wù),及SQL Server的聯(lián)機(jī)叢書:CLR 集成和事務(wù)

          使用顯式可分發(fā)事務(wù)進(jìn)行處理的示例代碼如下:

         1: public static void TestTransactionScopeInSQL2008()
         2: {
         3:     Action action = () => //1.把要執(zhí)行的操作封裝在一個(gè)或多個(gè)Action中
         4:     {
         5:         using (AdventureWorksDataContext context1 = new AdventureWorksDataContext())
         6:         {
         7:             context1.ExecuteCommand("Update TLinq SET Value={0}", 10);
         8:             List<TLINQ> linq = context1.TLINQ.ToList();
         9:             context1.TLINQ.InsertOnSubmit(new TLINQ() { Value = "1" });
        10:             linq.ForEach(e => e.Value = (Convert.ToInt32(e.Value) + 1).ToString());
        11:             context1.SubmitChanges();
        12:         }
        13:     };
        14:     TransactioExtension.Excute(action); 
        15: }

          或者這樣:

         1: /// <summary>
         2: /// 此方法里面完全不必考慮事務(wù)
         3: /// </summary>
         4: public static void TestTransactionScopeInSQL2008()
         5: {
         6:     using (AdventureWorksDataContext context1 = new AdventureWorksDataContext())
         7:     {
         8:         context1.ExecuteCommand("Update TLinq SET Value={0}", 10);
         9:         List<TLINQ> linq = context1.TLINQ.ToList();
        10:         context1.TLINQ.InsertOnSubmit(new TLINQ() { Value = "1" });
        11:         linq.ForEach(e => e.Value = (Convert.ToInt32(e.Value) + 1).ToString());
        12:         context1.SubmitChanges();
        13:     }
        14: }
        15:  
        16: //而在外面直接這樣使用
        17: TransactioExtension.Excute(() => TestTransactionScopeInSQL2008());

          灰常灰常地簡潔,把要執(zhí)行的操作封裝在一個(gè)或多個(gè)Action中,然后傳遞給TransactioExtension.Excute即可。對(duì)于封裝在TransactionScope里面執(zhí)行的所有操作(譬如SubmitChanges,ExcuteCommand、ExecuteQuery),最終都會(huì)解析為對(duì)ADO.NET的調(diào)用;而ADO.Net會(huì)在調(diào)用 Connection.Open 方法時(shí)自動(dòng)檢查Transaction.Current,并在該事務(wù)中以透明方式登記連接(除非在連接字符串中將 Enlist 關(guān)鍵字設(shè)置為 false)。

          SqlConnection 對(duì)象的 ConnectionString 屬性支持 Enlist 關(guān)鍵字,該關(guān)鍵字指示 System.Data.SqlClient 是否檢測(cè)事務(wù)上下文并在分布式事務(wù)中自動(dòng)登記連接。如果此關(guān)鍵字設(shè)置為 True(默認(rèn)設(shè)置),則會(huì)在打開的線程的當(dāng)前事務(wù)上下文中自動(dòng)登記連接。如果此關(guān)鍵字設(shè)置為 False,則 SqlClient 連接不會(huì)與分布式事務(wù)交互。如果未在連接字符串中指定 Enlist,并且如果在打開相應(yīng)連接時(shí)檢測(cè)到一個(gè)分布式事務(wù),則會(huì)在此分布式事務(wù)中自動(dòng)登記此連接。(FROM  Sql Server 2008 聯(lián)機(jī)叢書)

          關(guān)于TransactioExtension的封裝,代碼如下所示:(由于TransactionScope默認(rèn)的事務(wù)隔離級(jí)別是IsolationLevel.Serializable,這里調(diào)整為ReadCommitted隔離級(jí)別,以保持與Sql Server的默認(rèn)隔離級(jí)別一致):

         1: public static class TransactioExtension
         2: {
         3:     public static void Excute(params Action[] actions)
         4:     {
         5:         //使用ReadCommitted隔離級(jí)別,保持與Sql Server的默認(rèn)隔離級(jí)別一致
         6:         Excute(IsolationLevel.ReadCommitted, null, actions);
         7:     }
         8:  
         9:     public static void Excute(IsolationLevel level, params Action[] actions)
        10:     {
        11:         Excute(level, null, actions);
        12:     }
        13:  
        14:     public static void Excute(int timeOut, params Action[] actions)
        15:     {
        16:         Excute(IsolationLevel.ReadCommitted, timeOut, actions);
        17:     }
        18:  
        19:     public static void Excute(IsolationLevel level, int? timeOut, params Action[] actions)
        20:     {
        21:         if (actions == null || actions.Length == 0)
        22:             return;
        23:  
        24:         TransactionOptions options = new TransactionOptions();
        25:         options.IsolationLevel = level; //默認(rèn)為Serializable,這里根據(jù)參數(shù)來進(jìn)行調(diào)整
        26:         if(timeOut.HasValue)
        27:             options.Timeout = new TimeSpan(0, 0, timeOut.Value); //默認(rèn)60秒
        28:         using (TransactionScope tran = new TransactionScope(TransactionScopeOption.Required, options))
        29:         {
        30:             Array.ForEach<Action>(actions, action => action());
        31:             tran.Complete(); //通知事務(wù)管理器它可以提交事務(wù)
        32:         } 
        33:     }
        34: }

          不過在使用TransactionScope時(shí),需要注意,如果使用的數(shù)據(jù)庫是SQL Server 2000,或者需要實(shí)現(xiàn)跨多個(gè)數(shù)據(jù)庫進(jìn)行事務(wù)控制,則需要開啟DTC服務(wù)(位于:開始->管理工具->服務(wù)->Distributed Transaction Coordinator),下面是我的測(cè)試結(jié)果(我沒有裝SQL Server 2005,所以沒測(cè)2005的情況):

      測(cè)試環(huán)境 是否需要開啟DTC 創(chuàng)建出來的事務(wù)類型
      Linq to Sql + Sql Server 2000(單一數(shù)據(jù)庫) 需要 分布式事務(wù)
      Linq to Sql + Sql Server 2008(單一數(shù)據(jù)庫) 不需要 輕型本地事務(wù)
      Linq to Sql + Sql Server 2008(跨多個(gè)數(shù)據(jù)庫) 需要 訪問第一個(gè)數(shù)據(jù)庫時(shí),會(huì)創(chuàng)建輕型本地事務(wù);當(dāng)繼續(xù)訪問更多的數(shù)據(jù)庫時(shí),會(huì)將事務(wù)升級(jí)為完全可分發(fā)的分布式事務(wù)

          最后總結(jié)一下使用顯式可分發(fā)事務(wù)的優(yōu)缺點(diǎn):

          優(yōu)點(diǎn):使用簡單,可以配合ADO.Net或者DataContext.ExcuteCommand使用,可以跨DataContext使用,可以跨數(shù)據(jù)庫使用,可以跨服務(wù)器使用。

          缺點(diǎn):分布式事務(wù)通常會(huì)使用大量的系統(tǒng)資源。Microsoft 分布式事務(wù)處理協(xié)調(diào)器 (MS DTC) 會(huì)管理此類事務(wù),并集成在這些事務(wù)中訪問的所有資源管理器。慶幸的是:在打開一個(gè)具有活動(dòng)TransactionScope事務(wù)的連接而未打開任何其他連接的情況下,該事務(wù)會(huì)以輕型事務(wù)的形式提交,而不是產(chǎn)生完全分布式事務(wù)的額外開銷。

       

      最后來個(gè)匯總:

      事務(wù)類型 優(yōu)點(diǎn) 缺點(diǎn)
      隱式事務(wù) 使用簡單,由L2S自動(dòng)處理。 僅限于單個(gè)DataContext中的SubmitChanges方法內(nèi)使用。
      顯式本地事務(wù) 可以配合Ado.Net一起使用,可以跨多個(gè)DataContext來使用 使用相對(duì)繁瑣一點(diǎn)兒;且不支持與DataContext.ExecuteCommand配合使用
      顯式可分發(fā)事務(wù) 功能強(qiáng)大(可以配合ADO.Net或者DataContext.ExcuteCommand使用,可以跨DataContext使用,可以跨數(shù)據(jù)庫使用,可以跨服務(wù)器使用),使用簡單 可能會(huì)對(duì)性能有一些影響(我暫時(shí)也沒有測(cè)試過-,-)


       

       

      附:用Reflector查看DataContext.SubmitChanges的源代碼如下:

         1: public virtual void SubmitChanges(ConflictMode failureMode)
         2: {
         3:     this.CheckDispose();
         4:     this.CheckNotInSubmitChanges();
         5:     this.VerifyTrackingEnabled();
         6:     this.conflicts.Clear();
         7:     try
         8:     {
         9:         this.isInSubmitChanges = true;
        10:         if ((Transaction.Current == null) && (this.provider.Transaction == null)) //如果不在事務(wù)環(huán)境內(nèi)
        11:         {
        12:             bool flag = false;
        13:             DbTransaction transaction = null;
        14:             try
        15:             {
        16:                 if (this.provider.Connection.State == ConnectionState.Open)
        17:                 {
        18:                     this.provider.ClearConnection();
        19:                 }
        20:                 if (this.provider.Connection.State == ConnectionState.Closed)
        21:                 {
        22:                     this.provider.Connection.Open();
        23:                     flag = true;
        24:                 }
        25:                 transaction = this.provider.Connection.BeginTransaction(IsolationLevel.ReadCommitted); //開啟事務(wù)
        26:                 this.provider.Transaction = transaction;
        27:                 new ChangeProcessor(this.services, this).SubmitChanges(failureMode);
        28:                 this.AcceptChanges();
        29:                 this.provider.ClearConnection();
        30:                 transaction.Commit();
        31:                 return;
        32:             }
        33:             catch
        34:             {
        35:                 if (transaction != null)
        36:                 {
        37:                     try
        38:                     {
        39:                         transaction.Rollback();
        40:                     }
        41:                     catch
        42:                     {
        43:                     }
        44:                 }
        45:                 throw;
        46:             }
        47:             finally
        48:             {
        49:                 this.provider.Transaction = null;
        50:                 if (flag)
        51:                 {
        52:                     this.provider.Connection.Close();
        53:                 }
        54:             }
        55:         }
        56:         new ChangeProcessor(this.services, this).SubmitChanges(failureMode);
        57:         this.AcceptChanges();
        58:     }
        59:     finally
        60:     {
        61:         this.isInSubmitChanges = false;
        62:     }
        63: }
      posted on 2010-01-27 14:47  Silent Void  閱讀(22307)  評(píng)論(5)    收藏  舉報(bào)

      主站蜘蛛池模板: 国产偷人妻精品一区二区在线| 久久午夜无码鲁丝片直播午夜精品| 国99久9在线 | 免费| 九九久久精品国产| 日本一区二区三区在线看| 四川丰满少妇无套内谢| 井研县| 最新国产精品好看的精品| 4hu44四虎www在线影院麻豆| 中国极品少妇xxxxx| 亚洲色最新高清AV网站| 亚洲综合高清一区二区三区| 国自产拍偷拍精品啪啪一区二区| 国产精品老熟女乱一区二区| 久久99精品久久久久久9| 无码日韩精品一区二区三区免费 | 少妇人妻偷人精品免费| 亚洲精品日韩中文字幕| 亚洲午夜亚洲精品国产成人| 免费无码又爽又刺激高潮的app| 国产亚洲精品精品精品| 久久天天躁狠狠躁夜夜婷| 若尔盖县| 无码中文字幕热热久久| 国产成人综合欧美精品久久| 泾阳县| 久久人妻无码一区二区三区av| 荡乳尤物h| 亚洲精品香蕉一区二区| 在线国产精品中文字幕| AV最新高清无码专区| 94人妻少妇偷人精品| 女人被狂躁c到高潮| 国产精品一区二区性色av| 国产成人av电影在线观看第一页 | 国产欧美日韩另类精彩视频| 一本无码在线观看| 麻豆蜜桃伦理一区二区三区 | 亚洲精品国产中文字幕| 九九热免费公开视频在线| 亚洲毛片多多影院|