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

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

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

      LINQ-to-SQL那點事~LINQ-to-SQL中的數據緩存與應對

      回到目錄

      這個文章寫的有點滯后了,呵呵,因為總想把之前不確定的東西確定了之后,再寫這篇,之前的LINQ-to-SQL那點事,請點這里。

      LINQ-to-SQL中的數據緩存與應對

      Linq-to-SQL它是微軟自己推出的一個輕量級的ORM框架,它很好地完成了與SQLSERVER數據庫的映射(它目前只支持SQLSERVER,也不會有以后的,因為微軟不對它進行更新了),在使用它時,微軟提出了“數據上下文”的概念,這個上下文(context)類似于HttpContext,RequestContext,是指對某種事物的完整的抽象,把對這種事物的操作都集成在上下文中。

      Linq-to-SQL的上下文被稱為DataContext,它進一步的封裝了SQL語句,亮點在于它的查詢上,支持延時查詢,再配合linq的語法,使得開發人員在寫代碼時很優雅,代碼表現力更強。

      DataContext在性能方面提出了緩存的概念,它可以裝查詢出來的數據緩存到上下文中(這有時會產生并發問題),對于Insert,Update,Delete這類執行類操作也提供了緩存語句,每當SubmitChange方法被觸發時,這時緩存的語句被一次性的提交到SQLSERVER,之后將當前上下文的緩存語句清空。

      一個線程單例的數據上下文的提出:

      當你希望把延時的數據返回到表示層時,DataContext如果被dispose之后,這種操作是不被允許的,這是正確的,因為你的數據上下文可能在表示層方法執行前已經被dispose了,一般這種代碼會被這樣書寫:

          public IQueryable<Order_Info> GetOrder_Info(Expression<Func<Order_Info, bool>> predicate)
              {
                  using (var datacontext = new LinqDataContext())
                  {
                      return datacontext.Where(predicate);
                  }
              }

      這段代碼在執行上當然是有問題的,使用了using關鍵字后,在方法return這數據上下文DataContext將會被dispose,這是正常的,而由于linq語句返回的是IQueryable延時結果集,它將不會立即執行,只有真正返回數據時才會通過DataContext與SQLSERVER進行交互,而在上層方法中,由于DataContext這時已經被dispose了,所以,語句最終會報異常。

      面對這種問題,我們知道了它的原因,所以接下來就尋找一種解決方法,即不叫DataContext立即dispose的方法,你可能會很容易的想到“把using去掉不就可以了”,事實上,如果你對linq to sql了解的話,這種做法是不可取的,因為這樣,你在業務邏輯層無法實現“復雜查詢,linq join”(一般地,我們為每個DAL層的表對象寫幾個方法,可能是根據條件去查詢數據的方法),為什么呢?因為,對于一個linq查詢語句來說,你的數據上下文必須是同一個才行,如果用戶業務使用一個上下文,而訂單業務使用另一個上下文,那么,這兩個業務進行組成查詢時,就會出現不同數據上下文的問題。

      代碼可能是這樣:

         var linq =from user in userBLL().GetModel()
                   join order in orderBLL().GetModel() on user.UserID equals order.UserID
                    select new user_Ext
      { ... }

      為數據上下文添加一個工廠,用來生成由UI線程產生的數據上下文,再把這些上下文放在一個由UI線程作為鍵的字典里,當UI線程中的數據上下文在進行SubmitChange出現異常進,我們再將當然上下文dispose,并從數據上下文字典中移除它。

      數據上下文工廠及數據上下文基類代碼如下:

          /// <summary>
          /// 數據庫建立工廠
          /// Created By : 張占嶺
          /// Created Date:2011-10-14
          /// Modify By:
          /// Modify Date:
          /// Modify Reason:
          /// </summary>
          internal static class DbFactory
          {
              #region Fields
              static readonly string strConn = System.Configuration.ConfigurationManager.ConnectionStrings["test"].ToString();
              static System.Timers.Timer sysTimer;
              volatile static Dictionary<Thread, DataContext[]> divDataContext;
              #endregion
      
              #region Constructors
              static DbFactory()
              {
                  divDataContext = new Dictionary<Thread, DataContext[]>();
                  sysTimer = new System.Timers.Timer(10000);
                  sysTimer.AutoReset = true;
                  sysTimer.Enabled = true;
                  sysTimer.Elapsed += new System.Timers.ElapsedEventHandler(sysTimer_Elapsed);
                  sysTimer.Start();
              }
              #endregion
      
              #region Private Methods
              /// <summary>
              /// 清理DbContext上下文
              /// </summary>
              /// <param name="sender"></param>
              /// <param name="e"></param>
              static void sysTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
              {
                  List<Thread> list = divDataContext.Keys
                                                    .Where(item => item.ThreadState == ThreadState.Stopped)
                                                    .ToList();
                  if (list != null && list.Count > 0)
                  {
                      foreach (var thread in list)
                      {
                          foreach (var context in divDataContext[thread])
                          {
                              if (context != null)
                                  context.Dispose();
                          }
                      }
                  }
              }
              #endregion
      
              #region Public Methods
              /// <summary>
              /// 通過工廠的制造模式獲取相應的LINQ數據庫連接對象
              /// </summary>
              /// <param name="dbName">數據庫名稱(需要與真實數據庫名稱保持一致)</param>
              /// <returns>LINQ數據庫連接對象</returns>
              public static DataContext Intance(string dbName)
              {
                  return Intance(dbName, Thread.CurrentThread);
              }
      
              /// <summary>
              /// 通過工廠的制造模式獲取相應的LINQ數據庫連接對象
              /// </summary>
              /// <param name="dbName">數據庫名稱(需要與真實數據庫名稱保持一致)</param>
              /// <param name="thread">當前線程引用的對象</param>
              /// <returns>LINQ數據庫連接對象</returns>
              public static DataContext Intance(string dbName, Thread thread)
              {
      
                  if (!divDataContext.Keys.Contains(thread))
                  {
                      divDataContext.Add(thread, new DataContext[3]);
                  }
      
                  if (dbName.Equals("test"))
                  {
                      if (divDataContext[thread][0] == null)
                      {
                          divDataContext[thread][0] = new DAL.dbDataContext(strConn);
                      }
                      return divDataContext[thread][0];
                  }
      
      return null;
      
              }
      
              /// <summary>
              /// 手動清除數據上下文,根據線程
              /// </summary>
              /// <param name="thread"></param>
              public static void ClearContextByThread(Thread thread, DataContext db)
              {
                  divDataContext.Remove(thread);//從線程字典中移除
                  db.Dispose();//釋放數據資源
              }
              #endregion
      
          }

       

      下面是DataContext基類,已經對SubmitChanges(SaveChanges)方法進行了優化,手動dispose上下文。

      /// <summary>
          /// Repository基類
          /// 所有linqTosql上下文對象都繼承它
          /// </summary>
          public abstract class ContextBase
          {
              protected DataContext _db { get; private set; }
              protected IUnitOfWork UnitOfWork { get; private set; }
              public ContextBase(DataContext db)
              {
                  _db = db;
                  UnitOfWork = (IUnitOfWork)db;
              }
              public void SaveChanges()
              {
                  ChangeSet cSet = _db.GetChangeSet();
                  if ((cSet.Inserts.Count > 0
                      || cSet.Updates.Count > 0
                      || cSet.Deletes.Count > 0)
                      && !UnitOfWork.IsNotSubmit)
                  {
                      try
                      {
                          UnitOfWork.SaveChanges();
                      }
                      catch (System.Data.Linq.ChangeConflictException)
                      {
                          foreach (System.Data.Linq.ObjectChangeConflict occ in _db.ChangeConflicts)
                          {
                              // 使用當前數據庫中的值,覆蓋Linq緩存中實體對象的值  
                              occ.Resolve(System.Data.Linq.RefreshMode.OverwriteCurrentValues);
                              // 使用Linq緩存中實體對象的值,覆蓋當前數據庫中的值  
                              occ.Resolve(System.Data.Linq.RefreshMode.KeepCurrentValues);
                              // 只更新實體對象中改變的字段的值,其他的保留不變  
                              occ.Resolve(System.Data.Linq.RefreshMode.KeepChanges);
                          }
                          UnitOfWork.SaveChanges();
                      }
                    catch (Exception)//如果出現異常,就從數據字典中清除這個鍵值對
                      {
                          DbFactory.ClearContextByThread(System.Threading.Thread.CurrentThread, _db);
                    }
                  }
              }
          }

      下面是一個領域的repository基類,代碼如下:

          /// <summary>
          /// Test數據庫基類
          /// Created By : 張占嶺
          /// Created Date:2011-10-14
          /// Modify By:
          /// Modify Date:
          /// Modify Reason:
          /// </summary>
          public abstract class TestBase : ContextBase
          {
              #region Constructors
              public EEE114Base()
                  : this(null)
              { }
      
              public EEE114Base(IUnitOfWork db)
                  : base((DataContext)db ?? DbFactory.Intance("test", Thread.CurrentThread))
              { }
              #endregion
      
              #region Protected Properies
              /// <summary>
              /// 可以使用的數據庫連接對象
              /// [xxb]
              /// </summary>
              protected dbDataContext db
              {
                  get
                  {
                      return (dbDataContext)base._db;
                  }
              }
      
              #endregion
       }
      }

      OK,這就是改善之后的linq to sql架構的核心代碼,主要體現在生成數據上下文對象上,及如何去避免并發沖突的產生,而對于并發沖突我們會在另一篇文章中做詳細的說明。敬請期待!

      回到目錄

      posted @ 2013-06-19 14:18  張占嶺  閱讀(3970)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 国产精品一区二区三区91| 亚洲少妇人妻无码视频| 欧美激情内射喷水高潮| 久久久久国产精品人妻| 亚洲国产片一区二区三区| 中文字幕理伦午夜福利片| 一边添奶一边添p好爽视频| 国产精品妇女一区二区三区| 国产福利在线观看免费第一福利 | 国语精品国内自产视频| 一卡2卡三卡4卡免费网站| 精品人妻伦一二二区久久| 国产伦一区二区三区久久| 精品人妻中文字幕在线| 久久这里只精品国产2| 亚洲αⅴ无码乱码在线观看性色| 好深好湿好硬顶到了好爽| 内射中出无码护士在线| 午夜欧美日韩在线视频播放 | 中文字幕一区二区三区麻豆 | 国产成人亚洲精品自产在线| 天天看片视频免费观看| 国产超碰无码最新上传| 少妇伦子伦情品无吗| 国产愉拍精品手机| 精品国产午夜福利在线观看| 色宅男看片午夜大片啪啪| 蜜桃视频一区二区在线观看| 国产探花在线精品一区二区| 亚洲中文字幕无码久久2020| 玩弄放荡人妻少妇系列| 伊人蕉影院久亚洲高清| 丰满妇女强制高潮18xxxx | 久久99久国产麻精品66| 国产永久免费高清在线| 精品一区二区三区蜜桃麻豆| 久久精品国产清自在天天线| 中文 在线 日韩 亚洲 欧美| 亚洲日韩乱码一区二区三区四区| 国产成人午夜精品永久免费| 欧洲亚洲精品免费二区|