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

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

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

      LINQ之路10:LINQ to SQL 和 Entity Framework(下)

      在本篇中,我們將接著上一篇“LINQ to SQL 和 Entity Framework(上)”的內容,繼續使用LINQ to SQL和Entity Framework來實踐“解釋查詢”,學習這些技術的關鍵特性。我們在此關注的是LINQ to SQL和Entity Framework中的”LINQ”部分,并會比較這兩種技術的相同和不同之處。通過我們之前介紹的LINQ知識還有將來會討論的更多LINQ Operators,相信閱者能針對LINQ to SQL和Entity Framework寫出優雅高效的查詢。為了簡單清晰,文中有些地方對LINQ to SQL和Entity Framework進行了縮寫,分別為:L2S和EF。

      LINQ to SQL和Entity Framework的延遲執行

      和本地查詢一樣,L2S和EF查詢也是延遲執行的,這樣就允許我們漸進地創建LINQ查詢。但是,有一個方面,L2S和EF有自己特殊的延遲執行語義,這就是當一個子查詢出現在Select表達式中時:

      • 對于本地查詢,你獲得了兩個延遲執行,因為從功能角度來看,你選擇了包含多個查詢的一個sequence。若以當你遍歷外層結果sequence時,并不會遍歷內部子查詢,所以子查詢此時也就不會執行。
      • 而對于L2S/EF,子查詢和外層的主查詢在同一時間被執行,這樣就避免了過度的連接遠程數據庫導致性能問題。

      比如,對于L2S/EF,下面的查詢在第一個foreach語句時執行,且只執行一次:

                  var context = new LifePoemContext("database connection string");

      var query = from c in context.Customers
      select
      from o in context.Orders
      select new { c.Name, o.Price };

      foreach (var customerOrders in query)
      foreach (var namePrice in customerOrders)
      Console.WriteLine(namePrice.Name + " spent " + namePrice.Price);

      換句話說,我們在select表達式中明確指定的EntitySets/EntityCollections總是在一次執行中就能被獲取到:

                  var context = new LifePoemContext("database connection string");
      var query = from c in context.Customers
      select new { c.Name, c.Orders };

      foreach (var row in query)
      foreach (var order in row.Orders) // 沒有額外的連接查詢
      Console.WriteLine(row.Name + " spent " + order.Price);

      但如果我們沒有事先進行數據轉換,就對EntitySet/EntityCollection屬性進行遍歷的話,就會適用于延遲執行。下面的示例中,L2S和EF在每一次循環中都會執行另外的Orders查詢:

                  context.ContextOptions.DeferredLoadingEnabled = true;   // 僅EF需要此句

      foreach (Customer c in context.Customers)
      foreach (Order o in c.Orders) // 每次都會開始一個新的SQL查詢
      Console.WriteLine(c.Name + " spent " + o.Price);

      這種模式在我們需要有條件的執行內部查詢時具有優勢,比如我們可能需要依靠客戶端來做某個條件測試時:

                  foreach (Customer c in context.Customers)
      if(myWebService.HasBadCreditHistory(c.ID))
      foreach (Order o in c.Orders) // 開始一個新的SQL查詢
      Console.WriteLine(c.Name + " spent " + o.Price);

      上面我們看到了如何對關聯屬性進行顯示的數據轉換(select)來避免重復執行。稍后我們就會看到,L2S和EF還提供了其他的機制來實現這個功能。

       

      DataLoadOptions

      DataLoadOptions類是L2S的特性,它有兩個特殊的作用:

      • AssociateWith讓你能夠事先對EntitySet關聯設置過濾條件
      • LoadWith讓你能夠設置某些EntitySets為主動加載(eager loading),從而減少連接數據庫的次數

      設置過濾條件

      假如我們只關心那些Price大于1000的Orders,我們就可以通過DataLoadOptions來設置過濾條件:

                  var context = new LifePoemContext("database connection string");

      DataLoadOptions options = new DataLoadOptions();
      options.AssociateWith<Customer>(c => c.Orders.Where(order => order.Price > 1000));
      context.LoadOptions = options;

      foreach (Customer c in context.Customers)
      if (myWebService.HasBadCreditHistory(c.ID))
      ProcessCustomer(c); // 如果在該方法中引用c.Orders,只有那些Price > 1000的Orders被返回

      這會指示我們的DataContext實例總是使用給定的條件對Customer的Orders進行過濾。需要注意的是,AssociateWith并不會改變延遲執行的語義,它只是命令對特定的關系進行隱式的過濾。

      主動加載(Eager Loading)

      DataLoadOptions的第二個作用是請求讓某個EntitySets跟隨父EntitySets一起加載。比如,假設你想在加載所有Customers的同時一起加載他們的Orders,而不是對每一個Customer分別查詢一次Orders:

                  var context = new LifePoemContext("database connection string");

      DataLoadOptions options = new DataLoadOptions();
      options.LoadWith<Customer>(c => c.Orders);
      context.LoadOptions = options;

      foreach (Customer c in context.Customers) // 一次查詢
      foreach (Order o in c.Orders) // 因為上面的DataLoadOptions,所有的Orders都在上面的查詢中被同時Load了
      Console.WriteLine(c.Name + " bought a " + o.Description);

      這會指示DataContext,不論何時,只要一個Customer被獲取,它的Orders也會在同一時間被加載。我們可以組合LoadWith和AssociateWith方法,這樣既能獲得主動加載,還能對加載的EntitySets進行過濾,比如:

                  DataLoadOptions options = new DataLoadOptions();
      options.LoadWith<Customer>(c => c.Orders);
      options.AssociateWith<Customer>(c => c.Orders.Where(order => order.Price > 1000));

      Entity Framework中的主動加載(Eager Loading)

      在Entity Framework中,如果我們希望某個關聯的EntitySets被主動加載,則可以使用Include方法。下面的代碼就是在一個SQL查詢中,獲取所有的Customers和他們的Orders:

                  foreach (var c in context.Customers.Include("Orders"))
      foreach (var order in c.Orders)
      Console.WriteLine(order.Description);

      Include可以被級聯使用,假如每個Order都有OrderDetails和SalesPersons導航屬性的話,我們可以寫出如下的查詢讓這些數據也被一同加載:

                  context.Customers.Include("Orders.OrderDetails")
      .Include("Orders.SalesPersons")

       

      更新

      L2S和EF也會跟蹤你對Entities所做的修改并允許你把他們更新到數據庫。對于L2S,我們調用DataContext對象的SubmitChanges方法;而對于EF,我們調用ObjectContext對象的SaveChagnes方法。

      L2S的Table<>類提供了InsertOnSubmit和DeleteOnSubmit方法讓我們從一個表中插入或刪除行;EF的ObjectSet<>類則提供了AddObject和DeleteObject方法來實現相同的功能,請看下面的代碼示例:

                  var context = new LifePoemContext("database connection string");

      Customer cust = new Customer { ID = 1000, Name = "Yoyoo" };
      context.Customers.InsertOnSubmit(cust); // 插入Customer,在EF中使用AddObject
      context.SubmitChanges(); // 在EF中使用SaveChanges

      // 現在我們獲取上面插入的數據行,對其進行更新,然后刪除它
      Customer cust2 = context.Customers.Single(c => c.ID == 1000);
      cust2.Name = "Yoyoo2";
      context.SubmitChanges(); // 更新Customer

      context.Customers.DeleteOnSubmit(cust2); //在EF中使用DeleteObject
      context.SubmitChanges(); // 刪除Customer

      SubmitChanges/SaveChanges會收集自context創建(或上一次Save)以來對entities所做的所有修改,然后執行一個SQL語句來把他們寫回數據庫。

      我們還可以調用Add方法來向一個EntitySet/EntitiyCollection添加數據行,在執行SubmitChanges或SaveChanges,L2S和EF會自動生成相應的外鍵:

                  Order o1 = new Order { ID = 100, OrderDate = DateTime.Now, Price = 100 };
      Order o2 = new Order { ID = 101, OrderDate = DateTime.Now, Price = 500 };

      Customer cust = context.Customers.Single(c => c.ID == 1);
      cust.Orders.Add(o1);
      cust.Orders.Add(o2);

      context.SubmitChanges();

      在這個例子中,L2S/EF會自動把外鍵值1寫入新增的Order的CustomerID列,這是因為我們為Customer和Order定義了關聯屬性,如:

              // With L2S
      [Association(Name="Customer_Order", Storage="_Orders", ThisKey="ID", OtherKey="CustomerID")]
      public EntitySet<Order> Orders { get {...} set {...} }

      當你從一個EntitySet/EntityCollection中移除某行數據時,他的外鍵列會被自動設置為null。下面的代面會在我們最近新增的兩個orders和他們的Customer之間移除關聯,注意,只是去除關聯,Remove并不會刪除子entities:

                  var context = new LifePoemContext("database connection string");

      Customer cust = context.Customers.Single(c => c.ID == 1);
      cust.Orders.Remove(cust.Orders.Single(order => order.ID == 100));
      cust.Orders.Remove(cust.Orders.Single(order => order.ID == 101));

      context.SubmitChanges();

      因為上面的代碼會把每個Order的CustomerID列設為空,所以數據庫中Order.CustomerID列必需是可空的,否則會拋出異常。

      如果我們要完全刪除子entities,則需要調用DeleteOnSubmit:

                  // with L2S
      context.Orders.DeleteOnSubmit(context.Orders.Single(order => order.ID == 100));
      context.Orders.DeleteOnSubmit(context.Orders.Single(order => order.ID == 101));
      context.SubmitChanges();

      // with EF
      context.Orders.DeleteObject(context.Orders.Single(order => order.ID == 100));
      context.Orders.DeleteObject(context.Orders.Single(order => order.ID == 101));
      context.SaveChanges();

       

      LINQ to SQL和Entity Framework的API對比

      正如我們在這兩篇文章中看到的那樣,L2S和EF在LINQ查詢和數據更新方面非常相似,只是創建的對象或調用的方法有所不同罷了,下表總結了他們的API差異: 

      目的

      LINQ to SQL

      Entity Framework

      獲取保持所有CRUD操作的類

      DataContext

      ObjectContext

      從數據庫中(延遲)獲取某種類型的所有entities

      GetTable

      CreateObjectSet

      上面方法的返回類型

      Table<T>

      ObjectSet<T>

      提交對實體對象的更新

      SubmitChanges

      SaveChanges

      新增一個entity

      InsertOnSubmit

      AddObject

      刪除一個entity

      DeleteOnSubmit

      DeleteObject

      代表關聯屬性(有多個相關entities的那一方)的類型

      EntitySet<T>

      EntityCollection<T>

      代表關聯屬性(有多個相關entities的那一方)的類型(字段類型)

      EntityRef<T>

      EntityReference<T>

      裝載關聯屬性時的默認策略

      自動延遲加載

      明確調用

      主動加載(eager loading)

      DataLoadOptions

      .Include()

       

      通過這兩篇文章,我們有針對性的了解了L2S和EF在LINQ查詢支持上的特性。通過比較他們的異同,讓我們更好的他們的內在聯系和區分他們在使用上的差別。在接下來的幾篇博客中,我準備對LINQ查詢運算符(LINQ Operators)進行更加詳細的分類介紹。只有在了解了大多數查詢運算符后,才能更好的寫出功能強大而又簡潔優雅的 LINQ查詢。

      posted @ 2011-11-15 10:08  Life a Poem  閱讀(14114)  評論(17)    收藏  舉報
      主站蜘蛛池模板: 久久一日本综合色鬼综合色| 国内精品一区二区不卡| 内射视频福利在线观看| 在线无码午夜福利高潮视频| 九九热视频在线观看视频| 商南县| 日韩区二区三区中文字幕| 中文字幕国产日韩精品| 高清偷拍一区二区三区| 国产成人精品亚洲午夜| 草草线在成年免费视频2| 99国产精品一区二区蜜臀| 无遮挡aaaaa大片免费看| 91老熟女老人国产老太| 亚洲一区二区精品偷拍| 少妇人妻偷人精品系列| 日本边吃奶边摸边做在线视频| 国产精品香港三级国产av| 国色天香成人一区二区| 成人性生交大片免费看r链接| 亚洲精品国产熟女久久久| 国产区精品福利在线观看精品| 亚洲av永久一区二区| 高级艳妇交换俱乐部小说| 亚洲一区二区av高清| 91精品国产午夜福利| 国产精品不卡区一区二| 国产乱老熟女乱老熟女视频| 最新av中文字幕无码专区| 国产自拍偷拍视频在线观看| 亚洲高清WWW色好看美女| 国产高清无遮挡内容丰富| 18禁成人免费无码网站| 久久五月丁香合缴情网| 国产色婷婷亚洲99精品小说| 国产精品亚欧美一区二区三区| AV教师一区高清| 湖口县| 日韩深夜免费在线观看| 免费看成人欧美片爱潮app| 日韩丝袜欧美人妻制服|