Linq to SQL 參考Demo

   1 LINQ to SQL語句(1)之Where
   2  
   3 
   4 Where操做
   5  
   6 
   7 適用場景:實現過濾,查詢等功能。
   8 
   9  
  10 
  11 說明:與SQL命令中的Where做用類似,都是起到範圍限定也就是過濾做用的,而判斷條件就是它後面所接的子句。
  12 
  13  
  14 
  15 Where操做包括3種形式,分別爲簡單形式、關係條件形式、First()形式。下面分別用實例舉例下:
  16 
  17  
  18 
  19 1.簡單形式:
  20  
  21 
  22 例如:使用where篩選在倫敦的客戶
  23 
  24  
  25 
  26 var q =
  27 
  28   from c in db.Customers
  29 
  30   where c.City == "London"
  31 
  32   select c;
  33 
  34  
  35 
  36 再如:篩選1994 年或以後僱用的僱員:
  37 
  38  
  39 
  40 var q =
  41 
  42   from e in db.Employees
  43 
  44   where e.HireDate >= new DateTime(1994, 1, 1)
  45 
  46   select e;
  47 
  48 2.關係條件形式:
  49  
  50 
  51 篩選庫存量在定貨點水平之下但未斷貨的產品:
  52 
  53  
  54 
  55 var q =
  56 
  57   from p in db.Products
  58 
  59   where p.UnitsInStock <= p.ReorderLevel && !p.Discontinued
  60 
  61   select p;
  62 
  63  
  64 
  65 篩選出UnitPrice 大於10 或已停產的產品:
  66 
  67  
  68 
  69 var q =
  70 
  71   from p in db.Products
  72 
  73   where p.UnitPrice > 10m || p.Discontinued
  74 
  75   select p;
  76 
  77  
  78 
  79 下面這個例子是調用兩次where以篩選出UnitPrice大於10且已停產的產品。
  80 
  81  
  82 
  83 var q =
  84 
  85   db.Products.Where(p=>p.UnitPrice > 10m).Where(p=>p.Discontinued);
  86 
  87 3.First()形式:
  88  
  89 
  90 返回集合中的一個元素,其實質就是在SQL語句中加TOP (1)。
  91 
  92  
  93 
  94 簡單用法:選擇表中的第一個發貨方。
  95 
  96  
  97 
  98 Shipper shipper = db.Shippers.First();
  99 
 100  
 101 
 102 元素:選擇CustomerID 爲「BONAP」的單個客戶
 103 
 104  
 105 
 106 Customer cust = db.Customers.First(c =>c.CustomerID == "BONAP");
 107 
 108  
 109 
 110 條件:選擇運費大於 10.00 的訂單:
 111 
 112  
 113 
 114 Order ord = db.Orders.First(o =>o.Freight > 10.00M);
 115 
 116  
 117 
 118  
 119 
 120 LINQ to SQL語句(2)之Select/Distinct
 121  
 122 
 123 [1] Select介紹1
 124 
 125  
 126 
 127 [2] Select介紹2
 128 
 129  
 130 
 131 [3] Select介紹3和 Distinct介紹
 132 
 133  
 134 
 135 Select/Distinct操做符
 136 
 137  
 138 
 139 適用場景:o(∩_∩) o…查詢唄。
 140 
 141  
 142 
 143 說明:和SQL命令中的select做用類似但位置不一樣,查詢表達式中的select及所接子句是放在表達式最後並把子句中的變量也就是結果返回回來;延遲。
 144 
 145  
 146 
 147 Select/Distinct操做包括9種形式,分別爲簡單用 法、匿名類型形式、條件形式、指定類型形式、篩選形式、整形類型形式、嵌套類型形式、本地方法調用形式、Distinct形式。
 148 
 149  
 150 
 151 1.簡單用法:
 152  
 153 
 154 這個示例返回僅含客戶聯繫人姓名的序列。
 155 
 156  
 157 
 158 var q =
 159 
 160   from c in db.Customers
 161 
 162   select c.ContactName;
 163 
 164  
 165 
 166 注意:這個語句只是一個聲明或者一個描述,並無真正把數據取出來,只有當你須要該數據的時候,它纔會執行這個語句,這就是延遲加載(deferred loading)。若是,在聲明的時候就返回的結果集是對象的集合。你可使用ToList() 或ToArray()方法把查詢結果先進行保存,而後再對這個集合進行查詢。固然延遲加載(deferred loading)能夠像拼接SQL語句那樣拼接查詢語法,再執行它。
 167 
 168  
 169 
 170 2.匿名類型形式:
 171  
 172 
 173 說明:匿名類型是C#3.0中新特性。其實質是編譯器根據咱們自定義自動產生一個匿名的類來幫助咱們實現臨時變量的儲存。匿名類型還依賴於另一個特性:支持根據property來建立對象。好比,var d = new { Name = "s" };編譯器自動產生一個有property叫作Name的匿名類,而後按這 個類型分配內存,並初始化對象。可是var d = new {"s"};是編譯不 經過的。由於,編譯器不知道匿名類中的property的名字。例如stringc = "d";var d = new { c}; 則是能夠經過編譯的。編譯器會建立一個叫 作匿名類帶有叫c的property。
 174 
 175  
 176 
 177 例以下例:new {c,ContactName,c.Phone};ContactName和Phone都是在映射文件中定義與表中字 段相對應的property。編譯器讀取數據並建立對象時,會建立一個匿名類,這個 類有兩個屬性,爲ContactName和Phone,而後根據數據初始化對象。另外編譯器 還能夠重命名property的名字。
 178 
 179  
 180 
 181 var q =
 182 
 183   from c in db.Customers
 184 
 185   select new {c.ContactName, c.Phone};
 186 
 187  
 188 
 189 上面語句描述:使用 SELECT 和匿名類型返回僅含客戶聯繫人姓名和電話號碼的序列
 190 
 191  
 192 
 193 var q =
 194 
 195   from e in db.Employees
 196 
 197   select new
 198 
 199   {
 200 
 201     Name = e.FirstName + " " + e.LastName,
 202 
 203     Phone = e.HomePhone
 204 
 205   };
 206 
 207  
 208 
 209 上面語句描述:使用SELECT和匿名類型返回僅含僱員姓名和電話號碼的序列,並將 FirstName和LastName字段合併爲一個字段「Name」,此外在所得的序列中將HomePhone字段重命名爲Phone。
 210 
 211  
 212 
 213 var q =
 214 
 215   from p in db.Products
 216 
 217   select new
 218 
 219   {
 220 
 221      p.ProductID,
 222 
 223     HalfPrice = p.UnitPrice / 2
 224 
 225   };
 226 
 227  
 228 
 229 上面語句描述:使用SELECT和匿名類型返回全部產品的ID以及 HalfPrice(設置爲產品單價除以2所得的值)的序列。
 230 
 231  
 232 
 233 3.條件形式:
 234  
 235 
 236 說明:生成SQL語句爲:case when condition then else 237 
 238  
 239 
 240 var q =
 241 
 242   from p in db.Products
 243 
 244   select new
 245 
 246   {
 247 
 248     p.ProductName,
 249 
 250     Availability =
 251 
 252      p.UnitsInStock - p.UnitsOnOrder < 0 ?
 253 
 254     "Out Of Stock" : "In Stock"
 255 
 256   };
 257 
 258  
 259 
 260 上面語句描述:使用SELECT和條件語句返回產品名稱和產品供貨狀態的序列。
 261 
 262  
 263 
 264 4.指定類型形式:
 265  
 266 
 267 說明:該形式返回你自定義類型的對象集。
 268 
 269  
 270 
 271 var q =
 272 
 273   from e in db.Employees
 274 
 275   select new Name
 276 
 277    {
 278 
 279     FirstName = e.FirstName,
 280 
 281     LastName = e.LastName
 282 
 283   };
 284 
 285  
 286 
 287 上面語句描述:使用SELECT和已知類型返回僱員姓名的序列。
 288 
 289  
 290 
 291 5.篩選形式:
 292  
 293 
 294 說明:結合where使用,起到過濾做用。
 295 
 296  
 297 
 298 var q =
 299 
 300   from c in db.Customers
 301 
 302    where c.City == "London"
 303 
 304   select c.ContactName;
 305 
 306  
 307 
 308 上面語句描述:使用SELECT和WHERE返回僅含倫敦客戶聯繫人姓名的序列。
 309 
 310  
 311 
 312 6.shaped形式(整形類型):
 313  
 314 
 315 說明:其select操做使用了匿名對象,而這個匿名對象中,其屬性也是個匿名對象。
 316 
 317  
 318 
 319 var q =
 320 
 321   from c in db.Customers
 322 
 323   select new {
 324 
 325     c.CustomerID,
 326 
 327     CompanyInfo = new {c.CompanyName, c.City, c.Country},
 328 
 329     ContactInfo = new {c.ContactName, c.ContactTitle}
 330 
 331   };
 332 
 333  
 334 
 335 語句描述:使用 SELECT 和匿名類型返回有關客戶的數據的整形子集。查詢顧客的ID和公司信息(公司名稱,城市,國家)以及聯繫信息(聯繫人和職位)。
 336 
 337  
 338 
 339 7.嵌套類型形式:
 340  
 341 
 342 說明:返回的對象集中的每一個對象DiscountedProducts屬性中,又包含一個集合。也就是每一個對象也是一個集合類。
 343 
 344  
 345 
 346 var q =
 347 
 348   from o in db.Orders
 349 
 350   select new {
 351 
 352      o.OrderID,
 353 
 354     DiscountedProducts =
 355 
 356       from od in o.OrderDetails
 357 
 358       where od.Discount > 0.0
 359 
 360       select od,
 361 
 362     FreeShippingDiscount = o.Freight
 363 
 364   };
 365 
 366  
 367 
 368 語句描述:使用嵌套查詢返回全部訂單及其OrderID 的序列、打折訂單中項目的子序列以及免送貨所省下的金額。
 369 
 370  
 371 
 372 8.本地方法調用形式(LocalMethodCall):
 373  
 374 
 375 這個例子在查詢中調用本地方法 PhoneNumberConverter將電話號碼轉換爲國際格式。
 376 
 377  
 378 
 379 var q = from c in db.Customers
 380 
 381      where c.Country == "UK" || c.Country == "USA"
 382 
 383      select new
 384 
 385      {
 386 
 387        c.CustomerID,
 388 
 389        c.CompanyName,
 390 
 391        Phone = c.Phone,
 392 
 393        InternationalPhone =
 394 
 395        PhoneNumberConverter(c.Country, c.Phone)
 396 
 397      };
 398 
 399  
 400 
 401 PhoneNumberConverter方法以下:
 402 
 403  
 404 
 405 public string PhoneNumberConverter(stringCountry, string Phone)
 406 
 407 {
 408 
 409   Phone = Phone.Replace(" ", "").Replace(")", ")-");
 410 
 411   switch (Country)
 412 
 413    {
 414 
 415     case "USA":
 416 
 417       return "1- " + Phone;
 418 
 419     case "UK":
 420 
 421        return "44-" + Phone;
 422 
 423     default:
 424 
 425       return Phone;
 426 
 427   }
 428 
 429 }
 430 
 431  
 432 
 433 下面也是使用了這個方法將電話號碼轉換爲國際格式並建立XDocument
 434 
 435  
 436 
 437 XDocument doc = new XDocument(
 438 
 439   new XElement("Customers", from c in db.Customers
 440 
 441        where c.Country == "UK" || c.Country == "USA"
 442 
 443        select (new XElement ("Customer",
 444 
 445            new XAttribute ("CustomerID", c.CustomerID),
 446 
 447            new XAttribute("CompanyName", c.CompanyName),
 448 
 449            new XAttribute("InterationalPhone",
 450 
 451             PhoneNumberConverter(c.Country, c.Phone))
 452 
 453            ))));
 454 
 455 9.Distinct形式:
 456  
 457 
 458 說明:篩選字段中不相同的值。用於查詢不重複的結果集。生成SQL語句爲:SELECT DISTINCT [City] FROM [Customers]
 459 
 460  
 461 
 462 var q = (
 463 
 464   from c in db.Customers
 465 
 466   select c.City )
 467 
 468   .Distinct();
 469 
 470  
 471 
 472 語句描述:查詢顧客覆蓋的國家。
 473 
 474  
 475 
 476  
 477 
 478 LINQ to SQL語句(3)之Count/Sum/Min/Max/Avg
 479 [1] Count/Sum講解
 480 
 481  
 482 
 483 [2] Min講解
 484 
 485  
 486 
 487 [3] Max講解
 488 
 489  
 490 
 491 [4] Average和Aggregate講解
 492 
 493  
 494 
 495 Count/Sum/Min/Max/Avg操做符
 496 
 497  
 498 
 499 適用場景:統計數據吧,好比統計一些數據的個數,求和,最小值,最大值,平均數。
 500 
 501  
 502 
 503 Count
 504 
 505  
 506 
 507 說明:返回集合中的元素個數,返回INT類型;不延遲。生成 SQL語句爲:SELECT COUNT(*) FROM
 508 
 509  
 510 
 511 1.簡單形式:
 512  
 513 
 514 獲得數據庫中客戶的數量:
 515 
 516  
 517 
 518 var q = db.Customers.Count();
 519 
 520  
 521 
 522 2.帶條件形式:
 523  
 524 
 525 獲得數據庫中未斷貨產品的數量:
 526 
 527  
 528 
 529 var q = db.Products.Count(p =>!p.Discontinued);
 530 
 531  
 532 
 533 LongCount
 534 
 535  
 536 
 537 說明:返回集合中的元素個數,返回LONG類型;不延遲。對於元素個數較多的集合可視狀況能夠選用LongCount來統計元素個數,它返回long類型,比較精確。生成 SQL語句爲:SELECT COUNT_BIG(*) FROM
 538 
 539  
 540 
 541 var q = db.Customers.LongCount();
 542 
 543  
 544 
 545 Sum
 546 
 547  
 548 
 549 說明:返回集合中數值類型元素之和,集合應爲INT類型集合;不延遲。生成SQL語句爲:SELECT SUM(…) FROM
 550 
 551  
 552 
 553 1.簡單形式:
 554  
 555 
 556 獲得全部訂單的總運費:
 557 
 558  
 559 
 560 var q = db.Orders.Select(o =>o.Freight).Sum();
 561 
 562  
 563 
 564 2.映射形式:
 565  
 566 
 567 獲得全部產品的定貨總數:
 568 
 569  
 570 
 571 var q = db.Products.Sum(p =>p.UnitsOnOrder);
 572 
 573 Min
 574 
 575 說明:返回集合中元素的最小值;不延遲。生成SQL語句爲:SELECT MIN(…) FROM
 576 
 577 1.簡單形式:
 578 
 579 查找任意產品的最低單價:
 580 
 581 var q = db.Products.Select(p => p.UnitPrice).Min();
 582 
 583  
 584 
 585 2.映射形式:
 586 
 587  
 588 
 589 查找任意訂單的最低運費:
 590 
 591  
 592 
 593 var q = db.Orders.Min(o => o.Freight);
 594 
 595  
 596 
 597  
 598 
 599 3.元素:
 600  
 601 
 602 查找每一個類別中單價最低的產品:
 603 
 604  
 605 
 606 var categories =
 607 
 608   from p in db.Products
 609 
 610   group p by p.CategoryID into g
 611 
 612   select new {
 613 
 614     CategoryID = g.Key,
 615 
 616      CheapestProducts =
 617 
 618       from p2 in g
 619 
 620        where p2.UnitPrice == g.Min(p3 => p3.UnitPrice)
 621 
 622        select p2
 623 
 624   };
 625 
 626 Max
 627 
 628 說明:返回集合中元素的最大值;不延遲。生成SQL語句爲:SELECT MAX(…) FROM
 629 
 630 1.簡單形式:
 631 查找任意僱員的最近僱用日期:
 632 
 633 var q = db.Employees.Select(e => e.HireDate).Max();
 634 
 635  
 636 
 637 2.映射形式:
 638  
 639 
 640 查找任意產品的最大庫存量:
 641 
 642  
 643 
 644 var q = db.Products.Max(p =>p.UnitsInStock);
 645 
 646  
 647 
 648 3.元素:
 649  
 650 
 651 查找每一個類別中單價最高的產品:
 652 
 653  
 654 
 655 var categories =
 656 
 657   from p in db.Products
 658 
 659    group p by p.CategoryID into g
 660 
 661   select new {
 662 
 663      g.Key,
 664 
 665     MostExpensiveProducts =
 666 
 667       from p2 in g
 668 
 669       where p2.UnitPrice == g.Max(p3 => p3.UnitPrice)
 670 
 671       select p2
 672 
 673   };
 674 
 675 Average
 676 
 677 說明:返回集合中的數值類型元素的平均值。集合應爲數字類型集合,其返回值類型爲double;不延遲。生成SQL語句爲:SELECT AVG(…) FROM
 678 
 679 1.簡單形式:
 680 獲得全部訂單的平均運費:
 681 
 682 var q = db.Orders.Select(o =>o.Freight).Average();
 683 
 684  
 685 
 686 2.映射形式:
 687  
 688 
 689 獲得全部產品的平均單價:
 690 
 691  
 692 
 693 var q = db.Products.Average(p => p.UnitPrice);
 694 
 695  
 696 
 697 3.元素:
 698  
 699 
 700 查找每一個類別中單價高於該類別平均單價的產品:
 701 
 702  
 703 
 704 var categories =
 705 
 706   from p in db.Products
 707 
 708   group p by p.CategoryID into g
 709 
 710   select new {
 711 
 712     g.Key,
 713 
 714     ExpensiveProducts =
 715 
 716       from p2 in g
 717 
 718       where p2.UnitPrice > g.Average (p3 => p3.UnitPrice)
 719 
 720       select p2
 721 
 722   };
 723 
 724  
 725 
 726 Aggregate
 727 
 728  
 729 
 730 說明:根據輸入的表達式獲取聚合值;不延遲。便是說:用一個種子值與當前元素經過指定的函數來進行對比來遍歷集合中的元素,符合條件的元素保留下來。若是沒有指定種子值的話,種子值默認爲集合的第一個元素。
 731 
 732  
 733 
 734  
 735 
 736 LINQ to SQL語句(4)之Join
 737 Join操做符
 738  
 739 
 740 適用場景:在咱們表關係中有一對一關係,一對多關係,多對多關係等。對各個表之間的關係,就用這些實現對多個表的操做。
 741 
 742  
 743 
 744 說明:在Join操做中,分別爲Join(Join查詢), SelectMany(Select一對多選擇) 和GroupJoin(分組Join查詢)。
 745 
 746  
 747 
 748 該擴展方法對兩個序列中鍵匹配的元素進行inner join操做
 749 
 750  
 751 
 752 SelectMany
 753 
 754  
 755 
 756 說明:咱們在寫查詢語句時,若是被翻譯成SelectMany須要知足2個條件。1:查詢語句中沒有join和into,2:必須出現EntitySet。在咱們表關係中有一對一關係,一對多關係,多對多關係等,下面分別介紹一下。
 757 
 758  
 759 
 760 1.一對多關係(1 to Many):
 761  
 762 
 763 var q =
 764 
 765   from c in db.Customers
 766 
 767   from o in c.Orders
 768 
 769   where c.City == "London"
 770 
 771   select o;
 772 
 773  
 774 
 775 語句描述:Customers與Orders是一對多關係。即Orders在Customers類中以 EntitySet形式出現。因此第二個from是從c.Orders而不是db.Orders裏進行篩選。這個例子在From子句中使用外鍵導航選擇倫敦客戶的全部訂單。
 776 
 777  
 778 
 779 var q =
 780 
 781   from p in db.Products
 782 
 783   where p.Supplier.Country == "USA" &&p.UnitsInStock == 0
 784 
 785   select p;
 786 
 787  
 788 
 789 語句描述:這一句使用了 p.Supplier.Country條件,間接關聯了Supplier表。這個例子在Where子句中使用外鍵導航篩選其供應商在美國且缺貨的產品。生成SQL語句爲:
 790 
 791  
 792 
 793 SELECT [t0].[ProductID],[t0].[ProductName], [t0]. [SupplierID],
 794 
 795 [t0].[CategoryID],[t0].[QuantityPerUnit],[t0].[UnitPrice],
 796 
 797 [t0].[UnitsInStock],[t0].[UnitsOnOrder],[t0]. [ReorderLevel],
 798 
 799 [t0].[Discontinued] FROM [dbo].[Products]AS [t0]
 800 
 801 LEFT OUTER JOIN [dbo].[Suppliers] AS [t1]ON
 802 
 803 [t1]. [SupplierID] = [t0].[SupplierID]
 804 
 805 WHERE ([t1].[Country] = @p0) AND([t0].[UnitsInStock] = @p1)
 806 
 807 -- @p0: Input NVarChar (Size = 3; Prec = 0;Scale = 0) [USA]
 808 
 809 -- @p1: Input Int (Size = 0; Prec = 0;Scale = 0) [0]
 810 
 811  
 812 
 813 2.多對多關係(Many to Many):
 814  
 815 
 816 var q =
 817 
 818   from e in db.Employees
 819 
 820   from et in e.EmployeeTerritories
 821 
 822   where e.City == "Seattle"
 823 
 824   select new
 825 
 826   {
 827 
 828     e.FirstName,
 829 
 830      e.LastName,
 831 
 832     et.Territory.TerritoryDescription
 833 
 834   };
 835 
 836  
 837 
 838 說明:多對多關係通常會涉及三個表(若是有一個表是自關聯的,那有可能只有2個表)。這一句語句涉及Employees, EmployeeTerritories, Territories三個表。它們的關係是1:M:1。Employees 和Territories沒有很明確的關係。
 839 
 840  
 841 
 842 語句描述:這個例子在From子句中使用外鍵導航篩選在西雅圖的僱員,同時列出其所在地區。這條生成SQL語句爲:
 843 
 844  
 845 
 846 SELECT [t0].[FirstName], [t0].[LastName],[t2]. [TerritoryDescription]
 847 
 848 FROM [dbo].[Employees] AS [t0] CROSS JOIN[dbo].[EmployeeTerritories]
 849 
 850 AS [t1] INNER JOIN [dbo]. [Territories] AS[t2] ON
 851 
 852 [t2].[TerritoryID] = [t1].[TerritoryID]
 853 
 854 WHERE ([t0].[City] = @p0) AND([t1].[EmployeeID] = [t0]. [EmployeeID])
 855 
 856 -- @p0: Input NVarChar (Size = 7; Prec = 0;Scale = 0) [Seattle]
 857 
 858  
 859 
 860  
 861 
 862 3.自聯接關係:
 863  
 864 
 865 var q =
 866 
 867   from e1 in db.Employees
 868 
 869   from e2 in e1.Employees
 870 
 871   where e1.City == e2.City
 872 
 873   select new {
 874 
 875     FirstName1 = e1.FirstName, LastName1 = e1.LastName,
 876 
 877     FirstName2 = e2.FirstName, LastName2 = e2.LastName,
 878 
 879     e1.City
 880 
 881   };
 882 
 883  
 884 
 885 語句描述:這個例子在select 子句中使用外鍵導航篩選成對的僱員,每對中一個僱員隸屬於另外一個僱員,且兩個僱員都來自相同城市。生成SQL語句爲:
 886 
 887  
 888 
 889 SELECT [t0].[FirstName] AS [FirstName1],[t0].[LastName] AS
 890 
 891 [LastName1],[t1].[FirstName] AS[FirstName2], [t1].[LastName] AS
 892 
 893 [LastName2],[t0].[City] FROM[dbo].[Employees] AS [t0],
 894 
 895 [dbo].[Employees] AS [t1] WHERE([t0].[City] = [t1]. [City]) AND
 896 
 897 ([t1].[ReportsTo] = [t0].[EmployeeID])
 898 
 899 GroupJoin
 900 
 901  
 902 
 903 像上面所說的,沒有join和into,被翻譯成 SelectMany,同時有join和into時,那麼就被翻譯爲GroupJoin。在這裏into的概念是對其結果進行從新命名。
 904 
 905  
 906 
 907 1.雙向聯接(Two way join):
 908  
 909 
 910 此示例顯式聯接兩個表並從這兩個表投影出結果:
 911 
 912  
 913 
 914 var q =
 915 
 916    from c in db.Customers
 917 
 918   join o in db.Orders on c.CustomerID
 919 
 920   equals o.CustomerID into orders
 921 
 922   select new
 923 
 924    {
 925 
 926     c.ContactName,
 927 
 928     OrderCount = orders.Count ()
 929 
 930   };
 931 
 932  
 933 
 934 說明:在一對多關係中,左邊是1,它每條記錄爲c(from c in db.Customers),右邊是Many,其每條記錄叫作o ( join o in db.Orders ),每對應左邊的一個c,就會有一組o,那這一組o,就叫作orders, 也就是說,咱們把一組o命名爲orders,這就是into用途。這也就是爲何在select語句中,orders能夠調用聚合函數Count。在T-SQL中,使用其內嵌的T- SQL返回值做爲字段值。如圖所示:
 935 
 936  
 937 
 938  
 939 
 940  
 941 
 942 生成SQL語句爲:
 943 
 944  
 945 
 946 SELECT [t0].[ContactName], (
 947 
 948   SELECT COUNT(*)
 949 
 950   FROM [dbo].[Orders] AS [t1]
 951 
 952    WHERE [t0].[CustomerID] = [t1].[CustomerID]
 953 
 954 ) AS [OrderCount]
 955 
 956 FROM [dbo].[Customers] AS [t0]
 957 
 958  
 959 
 960 2.三向聯接(There way join):
 961  
 962 
 963 此示例顯式聯接三個表並分別從每一個表投影出結果:
 964 
 965  
 966 
 967 var q =
 968 
 969   from c in db.Customers
 970 
 971   join o in db.Orders on c.CustomerID
 972 
 973   equals o.CustomerID into ords
 974 
 975   join e in db.Employees on c.City
 976 
 977   equals e.City into emps
 978 
 979   select new
 980 
 981   {
 982 
 983     c.ContactName,
 984 
 985     ords = ords.Count(),
 986 
 987     emps = emps.Count()
 988 
 989   };
 990 
 991  
 992 
 993 生成SQL語句爲:
 994 
 995  
 996 
 997 SELECT [t0]. [ContactName], (
 998 
 999   SELECT COUNT(*)
1000 
1001   FROM [dbo].[Orders] AS [t1]
1002 
1003   WHERE [t0].[CustomerID] = [t1].[CustomerID]
1004 
1005 ) AS [ords], (
1006 
1007 SELECT COUNT(*)
1008 
1009   FROM [dbo].[Employees] AS [t2]
1010 
1011   WHERE [t0].[City] = [t2].[City]
1012 
1013 ) AS [emps]
1014 
1015 FROM [dbo].[Customers] AS [t0]
1016 
1017  
1018 
1019 3.左外部聯接(Left Outer Join):
1020  
1021 
1022 此示例說明如何經過使用此示例說明如何經過使用 DefaultIfEmpty() 獲取左外部聯接。在僱員沒有訂單時,DefaultIfEmpty()方法返回null:
1023 
1024  
1025 
1026 var q =
1027 
1028   from e in db.Employees
1029 
1030    join o in db.Orders on e equals o.Employee into ords
1031 
1032   from o in ords.DefaultIfEmpty()
1033 
1034   select new
1035 
1036   {
1037 
1038      e.FirstName,
1039 
1040     e.LastName,
1041 
1042     Order = o
1043 
1044    };
1045 
1046  
1047 
1048 說明:以Employees左表,Orders右表,Orders 表中爲空時,用null值填充。Join的結果重命名ords,使用DefaultIfEmpty()函數對其再次查詢。其最後的結果中有個Order,由於from o in ords.DefaultIfEmpty() 是對 ords組再一次遍歷,因此,最後結果中的Order並非一個集合。可是,若是沒有from o in ords.DefaultIfEmpty() 這句,最後的select語句寫成selectnew { e.FirstName, e.LastName, Order = ords }的話,那麼Order就是一個集合。
1049 
1050  
1051 
1052 4.投影的Let賦值(Projectedlet assignment):
1053  
1054 
1055 說明:let語句是重命名。let位於第一個from和select語句之間。
1056 
1057  
1058 
1059 這個例子從聯接投影出最終「Let」表達式:
1060 
1061  
1062 
1063 var q =
1064 
1065   from c in db.Customers
1066 
1067   join o in db.Orders on c.CustomerID
1068 
1069    equals o.CustomerID into ords
1070 
1071   let z = c.City + c.Country
1072 
1073   from o in ords
1074 
1075   select new
1076 
1077   {
1078 
1079      c.ContactName,
1080 
1081     o.OrderID,
1082 
1083     z
1084 
1085   };
1086 
1087  
1088 
1089 5.組合鍵(Composite Key):
1090  
1091 
1092 這個例子顯示帶有組合鍵的聯接:
1093 
1094  
1095 
1096 var q =
1097 
1098   from o in db.Orders
1099 
1100   from p in db.Products
1101 
1102   join d in db.OrderDetails
1103 
1104     on new
1105 
1106     {
1107 
1108       o.OrderID,
1109 
1110        p.ProductID
1111 
1112     } equals
1113 
1114       new
1115 
1116       {
1117 
1118         d.OrderID,
1119 
1120          d.ProductID
1121 
1122       }
1123 
1124     into details
1125 
1126   from d in details
1127 
1128   select new
1129 
1130   {
1131 
1132     o.OrderID,
1133 
1134     p.ProductID,
1135 
1136     d.UnitPrice
1137 
1138   };
1139 
1140  
1141 
1142 說明:使用三個表,而且用匿名類來講明:使用三個表,而且用匿名類來表示它們之間的關係。它們之間的關係不能用一個鍵描述清楚,因此用匿名類,來表示組合鍵。還有一種是兩個表之間是用組合鍵表示關係的,不須要使用匿名類。
1143 
1144  
1145 
1146 6.可爲null/不可爲null的鍵關係 (Nullable/Nonnullable Key Relationship):
1147  
1148 
1149 這個實例顯示如何構造一側可爲 null 而另外一側不可爲 null 的聯接:
1150 
1151  
1152 
1153 var q =
1154 
1155    from o in db.Orders
1156 
1157   join e in db.Employees
1158 
1159     on o.EmployeeID equals
1160 
1161     (int?)e.EmployeeID into emps
1162 
1163   from e in emps
1164 
1165   select new
1166 
1167   {
1168 
1169      o.OrderID,
1170 
1171     e.FirstName
1172 
1173   };
1174 
1175  
1176 
1177 LINQ to SQL語句(5)之Order By
1178 Order By操做
1179  
1180 
1181 適用場景:對查詢出的語句進行排序,好比按時間排序等等。
1182 
1183  
1184 
1185 說明:按指定表達式對集合排序;延遲,:按指定表達式對集合排序;延遲,默認是升序,加上descending表示降序,對應的擴展方法是 OrderBy和OrderByDescending
1186 
1187  
1188 
1189 1.簡單形式
1190  
1191 
1192 這個例子使用 orderby 按僱用日期對僱員進行排序:
1193 
1194  
1195 
1196 var q =
1197 
1198   from e in db.Employees
1199 
1200   orderby e.HireDate
1201 
1202   select e;
1203 
1204  
1205 
1206 說明:默認爲升序
1207 
1208  
1209 
1210 2.帶條件形式
1211  
1212 
1213 注意:Where 和Order By的順序並不重要。而在T-SQL中,Where和Order By有嚴格的位置限制。
1214 
1215  
1216 
1217 var q =
1218 
1219   from o in db.Orders
1220 
1221   where o.ShipCity == "London"
1222 
1223   orderby o.Freight
1224 
1225    select o;
1226 
1227  
1228 
1229 語句描述:使用where和orderby按運費進行排序。
1230 
1231  
1232 
1233 3.降序排序
1234  
1235 
1236 var q =
1237 
1238   from p in db.Products
1239 
1240   orderby p.UnitPrice descending
1241 
1242   select p;
1243 
1244  
1245 
1246  
1247 
1248 4.ThenBy
1249  
1250 
1251 語句描述:使用複合的 orderby 對客戶進行排序,進行排序:
1252 
1253  
1254 
1255 var q =
1256 
1257   from c in db.Customers
1258 
1259   orderby c.City, c.ContactName
1260 
1261   select c;
1262 
1263  
1264 
1265 說明:按多個表達式進行排序,例如先按City排序,當City相同時,按ContactName排序。這一句用Lambda表達式像這樣寫:
1266 
1267  
1268 
1269 var q =
1270 
1271   .OrderBy(c => c.City)
1272 
1273   .ThenBy(c => c.ContactName).ToList();
1274 
1275  
1276 
1277 在T-SQL中沒有 ThenBy語句,其依然翻譯爲OrderBy,因此也能夠用下面語句來表達:
1278 
1279  
1280 
1281 var q =
1282 
1283   db.Customers
1284 
1285   .OrderBy(c => c.ContactName)
1286 
1287   .OrderBy(c => c.City).ToList ();
1288 
1289  
1290 
1291 所要注意的是,多個OrderBy操做時,級連方式是按逆序。對於降序的,用相應的降序操做符替換便可。
1292 
1293  
1294 
1295 var q =
1296 
1297    db.Customers
1298 
1299   .OrderByDescending(c => c.City)
1300 
1301   .ThenByDescending(c => c.ContactName).ToList();
1302 
1303  
1304 
1305 須要說明的是,OrderBy操做,不支持按type排序,也不支持匿名類。好比
1306 
1307  
1308 
1309 var q =
1310 
1311   db.Customers
1312 
1313   .OrderBy(c => new
1314 
1315   {
1316 
1317     c.City,
1318 
1319     c.ContactName
1320 
1321   }).ToList();
1322 
1323  
1324 
1325 會被拋出異常。錯誤是前面的操做有匿名類,再跟OrderBy時,比較的是類別。好比
1326 
1327  
1328 
1329 var q =
1330 
1331    db.Customers
1332 
1333   .Select(c => new
1334 
1335   {
1336 
1337      c.City,
1338 
1339     c.Address
1340 
1341   })
1342 
1343   .OrderBy(c => c).ToList();
1344 
1345  
1346 
1347 若是你想使用OrderBy(c => c),其前提條件是,前面步驟中,所產生的對象的類別必須爲C#語言的基本類型。好比下句,這裏 City爲string類型。
1348 
1349  
1350 
1351 var q =
1352 
1353   db.Customers
1354 
1355    .Select(c => c.City)
1356 
1357   .OrderBy(c => c).ToList ();
1358 
1359  
1360 
1361  
1362 
1363 5.ThenByDescending
1364  
1365 
1366 這兩個擴展方式都是用在 OrderBy/OrderByDescending以後的,第一個ThenBy/ThenByDescending擴展方法 做爲第二位排序依據,第二個ThenBy/ThenByDescending則做爲第三位排序依據 ,以此類推
1367 
1368  
1369 
1370 var q =
1371 
1372   from o in db.Orders
1373 
1374    where o.EmployeeID == 1
1375 
1376   orderby o.ShipCountry, o.Freight descending
1377 
1378   select o;
1379 
1380  
1381 
1382 語句描述:使用orderby先按發往國家再按運費從高到低的順序對 EmployeeID 1 的訂單進行排序。
1383 
1384  
1385 
1386 6. 帶GroupBy形式
1387  
1388 
1389 var q =
1390 
1391   from p in db.Products
1392 
1393    group p by p.CategoryID into g
1394 
1395   orderby g.Key
1396 
1397   select new {
1398 
1399     g.Key,
1400 
1401     MostExpensiveProducts =
1402 
1403       from p2 in g
1404 
1405       where p2.UnitPrice == g.Max(p3 => p3.UnitPrice)
1406 
1407       select p2
1408 
1409   };
1410 
1411  
1412 
1413 語句描述:使用orderby、Max 和 Group By 得出每種類別中單價最高的產品,並按 CategoryID 對這組產品進行排序。
1414 
1415  
1416 
1417 LINQ to SQL語句(6)之GroupBy/Having
1418 Group By/Having操做符
1419  
1420 
1421 適用場景:分組數據,爲咱們查找數據縮小範圍。
1422 
1423  
1424 
1425 說明:分配並返回對傳入參數進行分組操做後的可枚舉對象。分組;延遲
1426 
1427  
1428 
1429 1.簡單形式:
1430  
1431 
1432 var q =
1433 
1434   from p in db.Products
1435 
1436   group p by p.CategoryID into g
1437 
1438   select g;
1439 
1440  
1441 
1442 語句描述:使用Group By按CategoryID劃分產品。
1443 
1444  
1445 
1446 說明:from p in db.Products 表示從表中將產品對象取出來。group p by p.CategoryID into g表示對p按CategoryID字段歸類。其結果命名爲g,一旦重 新命名,p的做用域就結束了,因此,最後select時,只能select g。固然,也沒必要從新命名能夠這樣寫:
1447 
1448  
1449 
1450 var q =
1451 
1452   from p in db.Products
1453 
1454   group p by p.CategoryID;
1455 
1456  
1457 
1458 咱們用示意圖表示:
1459 
1460  
1461 
1462  
1463 
1464 若是想遍歷某類別中全部記錄,這樣:
1465 
1466  
1467 
1468 foreach (var gp in q)
1469 
1470 {
1471 
1472   if (gp.Key == 2)
1473 
1474   {
1475 
1476      foreach (var item in gp)
1477 
1478     {
1479 
1480       //do something
1481 
1482     }
1483 
1484   }
1485 
1486 }
1487 
1488  
1489 
1490 2.Select匿名類:
1491  
1492 
1493 var q =
1494 
1495   from p in db.Products
1496 
1497   group p by p.CategoryID into g
1498 
1499   select new { CategoryID = g.Key, g };
1500 
1501  
1502 
1503 說明:在這句LINQ語句中,有2個property:CategoryID和g。這個匿名類,其實質是對返回結果集從新進行了包裝。把g的property封裝成一個完整的分組。以下圖所示:
1504 
1505  
1506 
1507  
1508 
1509 若是想遍歷某匿名類中全部記錄,要這麼作:
1510 
1511  
1512 
1513 foreach (var gp in q)
1514 
1515 {
1516 
1517   if (gp.CategoryID == 2)
1518 
1519   {
1520 
1521     foreach (var item in gp.g)
1522 
1523     {
1524 
1525       //do something
1526 
1527     }
1528 
1529   }
1530 
1531 }
1532 
1533  
1534 
1535 3.最大值
1536  
1537 
1538 var q =
1539 
1540   from p in db.Products
1541 
1542   group p by p.CategoryID into g
1543 
1544   select new {
1545 
1546     g.Key,
1547 
1548     MaxPrice = g.Max(p => p.UnitPrice)
1549 
1550   };
1551 
1552  
1553 
1554 語句描述:使用Group By和Max查找每一個CategoryID的最高單價。
1555 
1556  
1557 
1558 說明:先按CategoryID歸類,判斷各個分類產品中單價最大的 Products。取出CategoryID值,並把UnitPrice值賦給MaxPrice。
1559 
1560  
1561 
1562 4.最小值
1563  
1564 
1565 var q =
1566 
1567   from p in db.Products
1568 
1569   group p by p.CategoryID into g
1570 
1571   select new {
1572 
1573     g.Key,
1574 
1575     MinPrice = g.Min(p => p.UnitPrice)
1576 
1577   };
1578 
1579  
1580 
1581 語句描述:使用Group By和Min查找每一個CategoryID的最低單價。
1582 
1583  
1584 
1585 說明:先按CategoryID歸類,判斷各個分類產品中單價最小的 Products。取出CategoryID值,並把UnitPrice值賦給MinPrice。
1586 
1587  
1588 
1589 5.平均值
1590  
1591 
1592 var q =
1593 
1594   from p in db.Products
1595 
1596   group p by p.CategoryID into g
1597 
1598   select new {
1599 
1600     g.Key,
1601 
1602     AveragePrice = g.Average(p => p.UnitPrice)
1603 
1604   };
1605 
1606  
1607 
1608 語句描述:使用Group By和Average獲得每一個CategoryID的平均單價。
1609 
1610  
1611 
1612 說明:先按CategoryID歸類,取出CategoryID值和各個分類產品中單價的平均值。
1613 
1614  
1615 
1616 6.求和
1617  
1618 
1619 var q =
1620 
1621   from p in db.Products
1622 
1623   group p by p.CategoryID into g
1624 
1625   select new {
1626 
1627     g.Key,
1628 
1629     TotalPrice = g.Sum(p => p.UnitPrice)
1630 
1631   };
1632 
1633  
1634 
1635 語句描述:使用Group By和Sum獲得每一個CategoryID 的單價總計。
1636 
1637  
1638 
1639 說明:先按CategoryID歸類,取出 CategoryID值和各個分類產品中單價的總和。
1640 
1641  
1642 
1643 7.計數
1644  
1645 
1646 var q =
1647 
1648   from p in db.Products
1649 
1650   group p by p.CategoryID into g
1651 
1652   select new {
1653 
1654     g.Key,
1655 
1656     NumProducts = g.Count()
1657 
1658   };
1659 
1660  
1661 
1662 語句描述:使用Group By和Count獲得每一個CategoryID中產品的數量。
1663 
1664  
1665 
1666 說明:先按CategoryID歸類,取出 CategoryID值和各個分類產品的數量。
1667 
1668  
1669 
1670 8.帶條件計數
1671  
1672 
1673 var q =
1674 
1675   from p in db.Products
1676 
1677   group p by p.CategoryID into g
1678 
1679   select new {
1680 
1681     g.Key,
1682 
1683     NumProducts = g.Count(p => p.Discontinued)
1684 
1685   };
1686 
1687  
1688 
1689 語句描述:使用Group By和Count獲得每一個CategoryID中斷貨產品的數量。
1690 
1691  
1692 
1693 說明:先按 CategoryID歸類,取出CategoryID值和各個分類產品的斷貨數量。Count函數裏,使用了Lambda表達式,Lambda表達式中的p,表明這個組裏的一個元素或對象,即某一個產品。
1694 
1695  
1696 
1697 9.Where限制
1698  
1699 
1700 var q =
1701 
1702   from p in db.Products
1703 
1704   group p by p.CategoryID into g
1705 
1706   where g.Count() >= 10
1707 
1708   select new {
1709 
1710     g.Key,
1711 
1712     ProductCount = g.Count()
1713 
1714   };
1715 
1716  
1717 
1718 語句描述:根據產品的―ID分組,查詢產品數量大於10的ID和產品數量。這個示例在Group By子句後使用Where子句查找全部至少有10種產品的類別。
1719 
1720  
1721 
1722 說明:在翻譯成SQL 語句時,在最外層嵌套了Where條件。
1723 
1724  
1725 
1726 10.多列(Multiple Columns)
1727  
1728 
1729 var categories =
1730 
1731   from p in db.Products
1732 
1733    group p by new
1734 
1735   {
1736 
1737     p.CategoryID,
1738 
1739      p.SupplierID
1740 
1741   }
1742 
1743     into g
1744 
1745     select new
1746 
1747       {
1748 
1749         g.Key,
1750 
1751         g
1752 
1753       };
1754 
1755  
1756 
1757 語句描述:使用Group By按CategoryID和 SupplierID將產品分組。
1758 
1759  
1760 
1761 說明:既按產品的分類,又按供應商分類。在 by後面,new出來一個匿名類。這裏,Key其實質是一個類的對象,Key包含兩個 Property:CategoryID、SupplierID。用g.Key.CategoryID能夠遍歷CategoryID 的值。
1762 
1763  
1764 
1765 11.表達式(Expression)
1766  
1767 
1768 var categories =
1769 
1770    from p in db.Products
1771 
1772   group p by new { Criterion = p.UnitPrice > 10 } into g
1773 
1774   select g;
1775 
1776  
1777 
1778 語句描述:使用Group By返回兩個產品序列。第一個序列包含單價大於10的產品。第二個序列包含單價小於或等於10的產品。
1779 
1780  
1781 
1782 說明:按產品單價是否大於10分類。其結果分爲兩類,大於的是一類,小於及等於爲另外一類。
1783 
1784  
1785 
1786 LINQ to SQL語句(7)之Exists/In/Any/All/Contains
1787 Exists/In/Any/All/Contains操做符
1788  
1789 
1790 適用場景:用於判斷集合中元素,進一步縮小範圍。
1791 
1792  
1793 
1794 Any
1795  
1796 
1797 說明:用於判斷集合中是否有元素知足某一條件;不延遲。(若條件爲空,則集合只要不爲空就返回True,不然爲 False)。有2種形式,分別爲簡單形式和帶條件形式。
1798 
1799  
1800 
1801 1.簡單形式:
1802  
1803 
1804 僅返回沒有訂單的客戶:
1805 
1806  
1807 
1808 var q =
1809 
1810   from c in db.Customers
1811 
1812   where !c.Orders.Any()
1813 
1814   select c;
1815 
1816  
1817 
1818 生成SQL語句爲:
1819 
1820  
1821 
1822 SELECT [t0].[CustomerID],[t0].[CompanyName], [t0].[ContactName],
1823 
1824 [t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region],
1825 
1826 [t0].[PostalCode], [t0].[Country],[t0].[Phone], [t0].[Fax]
1827 
1828 FROM [dbo].[Customers] AS [t0]
1829 
1830 WHERE NOT (EXISTS(
1831 
1832   SELECT NULL AS [EMPTY] FROM [dbo].[Orders] AS [t1]
1833 
1834   WHERE [t1].[CustomerID] = [t0]. [CustomerID]
1835 
1836   ))
1837 
1838  
1839 
1840 2.帶條件形式:
1841  
1842 
1843 僅返回至少有一種產品斷貨的類別:
1844 
1845  
1846 
1847 var q =
1848 
1849   from c in db.Categories
1850 
1851   where c.Products.Any(p => p.Discontinued)
1852 
1853   select c;
1854 
1855  
1856 
1857 生成SQL語句爲:
1858 
1859  
1860 
1861 SELECT [t0]. [CategoryID],[t0].[CategoryName], [t0].[Description],
1862 
1863 [t0]. [Picture] FROM [dbo].[Categories] AS[t0]
1864 
1865 WHERE EXISTS(
1866 
1867    SELECT NULL AS [EMPTY] FROM [dbo].[Products] AS [t1]
1868 
1869   WHERE ([t1].[Discontinued] = 1) AND
1870 
1871   ([t1].[CategoryID] = [t0]. [CategoryID])
1872 
1873   )
1874 
1875 All
1876 說明:用於判斷集合中全部元素是否都知足某一條件;不延遲1.帶條件形式
1877 
1878  
1879 
1880 var q =
1881 
1882   from c in db.Customers
1883 
1884   where c.Orders.All(o => o.ShipCity == c.City)
1885 
1886   select c;
1887 
1888  
1889 
1890 語句描述:這個例子返回全部訂單都運往其所在城市的客戶或未下訂單的客戶。
1891 
1892  
1893 
1894 Contains
1895  
1896 
1897 說明:用於判斷集合中是否包含有某一元素;不延遲。它是對兩個序列進行鏈接操做的。
1898 
1899  
1900 
1901 string[] customerID_Set =
1902 
1903   new string[] { "AROUT", "BOLID","FISSA" };
1904 
1905 var q = (
1906 
1907   from o in db.Orders
1908 
1909   where customerID_Set.Contains(o.CustomerID)
1910 
1911   select o).ToList ();
1912 
1913  
1914 
1915 語句描述:查找"AROUT", "BOLID""FISSA" 這三個客戶的訂單。先定義了一個數組,在LINQ to SQL中使用Contains,數組中包含了全部的CustomerID,即返回結果中,全部的 CustomerID都在這個集合內。也就是in。你也能夠把數組的定義放在LINQ to SQL語句裏。好比:
1916 
1917  
1918 
1919 var q = (
1920 
1921   from o in db.Orders
1922 
1923   where (
1924 
1925   new string[] { "AROUT", "BOLID","FISSA" })
1926 
1927   .Contains (o.CustomerID)
1928 
1929   select o).ToList();
1930 
1931 Not Contains則取反:
1932 
1933 var q = (
1934 
1935   from o in db.Orders
1936 
1937   where !(
1938 
1939   new string[] { "AROUT", "BOLID","FISSA" })
1940 
1941   .Contains(o.CustomerID)
1942 
1943   select o).ToList();
1944 
1945  
1946 
1947 1.包含一個對象:
1948  
1949 
1950 var order = (from o in db.Orders
1951 
1952        where o.OrderID == 10248
1953 
1954        select o).First();
1955 
1956 var q = db.Customers.Where(p =>p.Orders.Contains(order)).ToList();
1957 
1958 foreach (var cust in q)
1959 
1960 {
1961 
1962   foreach (var ord in cust.Orders)
1963 
1964   {
1965 
1966     //do something
1967 
1968   }
1969 
1970 }
1971 
1972  
1973 
1974 語句描述:這個例子使用Contain查找哪一個客戶包含OrderID爲10248的訂單。
1975 
1976  
1977 
1978 2.包含多個值:
1979  
1980 
1981 string[] cities =
1982 
1983   new string[] { "Seattle", "London","Vancouver", "Paris" };
1984 
1985 var q = db.Customers.Where(p=>cities.Contains(p.City)).ToList();
1986 
1987  
1988 
1989 語句描述:這個例子使用Contains查找其所在城市爲西雅圖、倫敦、巴黎或溫哥華的客戶。
1990 
1991  
1992 
1993  
1994 
1995 LINQ to SQL語句(8)之Concat/Union/Intersect/Except
1996 Concat/Union/Intersect/Except操做
1997  
1998 
1999 適用場景:對兩個集合的處理,例如追加、合併、取相同項、相交項等等。
2000 
2001  
2002 
2003 Concat(鏈接)
2004  
2005 
2006 說明:鏈接不一樣的集合,不會自動過濾相同項;延遲。
2007 
2008  
2009 
2010 1.簡單形式:
2011 var q = (
2012 
2013      from c in db.Customers
2014 
2015      select c.Phone
2016 
2017     ).Concat(
2018 
2019      from c in db.Customers
2020 
2021      select c.Fax
2022 
2023     ).Concat(
2024 
2025      from e in db.Employees
2026 
2027      select e.HomePhone
2028 
2029     );
2030 
2031  
2032 
2033 語句描述:返回全部消費者和僱員的電話和傳真。
2034 
2035  
2036 
2037 2.複合形式:
2038 var q = (
2039 
2040      from c in db.Customers
2041 
2042      select new
2043 
2044      {
2045 
2046        Name = c.CompanyName,
2047 
2048        c.Phone
2049 
2050      }
2051 
2052      ).Concat(
2053 
2054      from e in db.Employees
2055 
2056      select new
2057 
2058      {
2059 
2060        Name = e.FirstName + " " + e.LastName,
2061 
2062        Phone = e.HomePhone
2063 
2064      }
2065 
2066     );
2067 
2068  
2069 
2070 語句描述:返回全部消費者和僱員的姓名和電話。
2071 
2072  
2073 
2074 Union(合併)
2075  
2076 
2077 說明:鏈接不一樣的集合,自動過濾相同項;延遲。便是將兩個集合進行合併操做,過濾相同的項。
2078 
2079  
2080 
2081 var q = (
2082 
2083      from c in db.Customers
2084 
2085      select c.Country
2086 
2087     ).Union(
2088 
2089      from e in db.Employees
2090 
2091      select e.Country
2092 
2093     );
2094 
2095  
2096 
2097 語句描述:查詢顧客和職員所在的國家。
2098 
2099  
2100 
2101 Intersect(相交)
2102  
2103 
2104 說明:取相交項;延遲。便是獲取不一樣集合的相同項(交集)。即先遍歷第一個集合,找出全部惟一的元素,而後遍歷第二個集合,並將每一個元素與前面找出的元素做對比,返回全部在兩個集合內都出現的元素。
2105 
2106  
2107 
2108 var q = (
2109 
2110      from c in db.Customers
2111 
2112      select c.Country
2113 
2114     ).Intersect (
2115 
2116      from e in db.Employees
2117 
2118      select e.Country
2119 
2120     );
2121 
2122  
2123 
2124 語句描述:查詢顧客和職員同在的國家。
2125 
2126  
2127 
2128 Except(與非)
2129  
2130 
2131 說明:排除相交項;延遲。便是從某集合中刪除與另外一個集合中相同的項。先遍歷第一個集合,找出全部惟一的元素,而後再遍歷第二個集合,返回第二個集合中全部未出如今前面所得元素集合中的元素。
2132 
2133  
2134 
2135 var q = (
2136 
2137      from c in db.Customers
2138 
2139      select c.Country
2140 
2141     ).Except(
2142 
2143      from e in db.Employees
2144 
2145      select e.Country
2146 
2147     );
2148 
2149  
2150 
2151 語句描述:查詢顧客和職員不一樣的國家。
2152 
2153  
2154 
2155 LINQ to SQL語句(9)之Top/Bottom和Paging和SqlMethods
2156 Top/Bottom操做
2157  
2158 
2159 適用場景:適量的取出本身想要的數據,不是所有取出,這樣性能有所增強。
2160 
2161  
2162 
2163 Take
2164  
2165 
2166 說明:獲取集合的前n個元素;延遲。即只返回限定數量的結果集。
2167 
2168  
2169 
2170 var q = (
2171 
2172   from e in db.Employees
2173 
2174   orderby e.HireDate
2175 
2176   select e)
2177 
2178   .Take(5);
2179 
2180  
2181 
2182 語句描述:選擇所僱用的前5個僱員。
2183 
2184  
2185 
2186 Skip
2187  
2188 
2189 說明:跳過集合的前n個元素;延遲。即咱們跳過給定的數目返回後面的結果集。
2190 
2191  
2192 
2193 var q = (
2194 
2195   from p in db.Products
2196 
2197   orderby p.UnitPrice descending
2198 
2199   select p)
2200 
2201   .Skip (10);
2202 
2203  
2204 
2205 語句描述:選擇10種最貴產品以外的全部產品。
2206 
2207  
2208 
2209 TakeWhile
2210  
2211 
2212 說明:直到某一條件成立就中止獲取;延遲。即用其條件去依次判斷源序列中的元素,返回符合判斷條件的元素,該判斷操做將在返回 false或源序列的末尾結束。
2213 
2214  
2215 
2216 SkipWhile
2217  
2218 
2219 說明:直到某一條件成立就中止跳過;延遲。即用其條件去判斷源序列中的元素而且跳過第一個符合判斷條件的元素,一旦判斷返回false,接下來將再也不進行判斷並返回剩下的全部元素。
2220 
2221  
2222 
2223 Paging(分頁)操做
2224  
2225 
2226 適用場景:結合Skip和Take就可實現對數據分頁操做。
2227 
2228  
2229 
2230 1.索引
2231 var q = (
2232 
2233   from c in db.Customers
2234 
2235   orderby c.ContactName
2236 
2237   select c)
2238 
2239   .Skip(50)
2240 
2241   .Take(10);
2242 
2243  
2244 
2245 語句描述:使用Skip和Take運算符進行分頁,跳過前50條記錄,而後返回接下來10條記錄,所以提供顯示 Products表第6頁的數據。
2246 
2247  
2248 
2249 2.按惟一鍵排序
2250 var q = (
2251 
2252    from p in db.Products
2253 
2254   where p.ProductID > 50
2255 
2256    orderby p.ProductID
2257 
2258   select p)
2259 
2260   .Take(10);
2261 
2262  
2263 
2264 語句描述:使用Where子句和Take運算符進行分頁,首先篩選獲得僅50 (第5頁最後一個ProductID)以上的ProductID,而後按ProductID排序,最後取前10個結果,所以提供Products表第6頁的數據。請注意,此方法僅適用於按惟一鍵排序的狀況。
2265 
2266  
2267 
2268 SqlMethods操做
2269  
2270 
2271 在LINQ to SQL語句中,爲咱們提供了 SqlMethods操做,進一步爲咱們提供了方便,例如Like方法用於自定義通配表達式,Equals用於相比較是否相等。
2272 
2273  
2274 
2275 Like
2276  
2277 
2278 自定義的通配表達式。%表示零長度或任意長度的字符串;_表示一個字符;[]表示在某範圍區間的一個字符;[^]表示不在某範圍區間的一個字符。好比查詢消費者ID以「C」開頭的消費者。
2279 
2280  
2281 
2282 var q = from c in db.Customers
2283 
2284      where SqlMethods.Like(c.CustomerID, "C%")
2285 
2286      select c;
2287 
2288  
2289 
2290 好比查詢消費者ID沒有「AXOXT」形式的消費者:
2291 
2292  
2293 
2294 var q = from c in db.Customers
2295 
2296     where ! SqlMethods.Like(c.CustomerID, "A_O_T")
2297 
2298     select c;
2299 
2300 DateDiffDay
2301 
2302  
2303 
2304 說明:在兩個變量之間比較。分別有:DateDiffDay、 DateDiffHour、DateDiffMillisecond、DateDiffMinute、DateDiffMonth、 DateDiffSecond、DateDiffYear 
2305 
2306  
2307 
2308 var q = from o in db.Orders
2309 
2310     where SqlMethods
2311 
2312     .DateDiffDay (o.OrderDate, o.ShippedDate) < 10
2313 
2314     select o;
2315 
2316  
2317 
2318 語句描述:查詢在建立訂單後的 10 天內已發貨的全部訂單。
2319 
2320  
2321 
2322 已編譯查詢操做(Compiled Query)
2323  
2324 
2325 說明:在以前咱們沒有好的方法對寫出的SQL語句進行編輯從新查詢,如今咱們能夠這樣作,看下面一個例子:
2326 
2327  
2328 
2329 //1. 建立compiled query
2330 
2331 NorthwindDataContext db = newNorthwindDataContext();
2332 
2333 var fn = CompiledQuery.Compile(
2334 
2335    (NorthwindDataContext db2, string city) =>
2336 
2337   from c in db2.Customers
2338 
2339   where c.City == city
2340 
2341   select c);
2342 
2343 //2.查詢城市爲London的消費者,用LonCusts集合表示,這時能夠用數據控件 綁定
2344 
2345 var LonCusts = fn(db, "London");
2346 
2347 //3.查詢城市 爲Seattle的消費者
2348 
2349 var SeaCusts = fn(db, "Seattle");
2350 
2351  
2352 
2353 語句描述:這個例子建立一個已編譯查詢,而後使用它檢索輸入城市的客戶。
2354 
2355  
2356 
2357 LINQ to SQL語句(10)之Insert
2358 插入(Insert)1.簡單形式
2359  
2360 
2361 說明:new一個對象,使用InsertOnSubmit方法將其加入到對應的集合中,使用SubmitChanges()提交到數據庫。
2362 
2363  
2364 
2365 NorthwindDataContext db = newNorthwindDataContext();
2366 
2367 var newCustomer = new Customer
2368 
2369 {
2370 
2371   CustomerID = "MCSFT",
2372 
2373   CompanyName = "Microsoft",
2374 
2375   ContactName = "John Doe",
2376 
2377   ContactTitle = "Sales Manager",
2378 
2379   Address = "1 Microsoft Way",
2380 
2381   City = "Redmond",
2382 
2383   Region = "WA",
2384 
2385   PostalCode = "98052",
2386 
2387    Country = "USA",
2388 
2389   Phone = "(425) 555- 1234",
2390 
2391   Fax = null
2392 
2393 };
2394 
2395 db.Customers.InsertOnSubmit(newCustomer);
2396 
2397 db.SubmitChanges ();
2398 
2399  
2400 
2401 語句描述:使用InsertOnSubmit方法將新客戶添加到Customers 表對象。調用SubmitChanges 將此新Customer保存到數據庫。
2402 
2403  
2404 
2405 2.一對多關係
2406  
2407 
2408 說明:Category與Product是一對多的關係,提交Category(一端)的數據時,LINQ to SQL會自動將Product(多端)的數據一塊兒提交。
2409 
2410  
2411 
2412 var newCategory = new Category
2413 
2414 {
2415 
2416   CategoryName = "Widgets",
2417 
2418   Description = "Widgets are the ……"
2419 
2420 };
2421 
2422 var newProduct = new Product
2423 
2424 {
2425 
2426   ProductName = "Blue Widget",
2427 
2428   UnitPrice = 34.56M,
2429 
2430   Category = newCategory
2431 
2432 };
2433 
2434 db.Categories.InsertOnSubmit(newCategory);
2435 
2436 db.SubmitChanges ();
2437 
2438  
2439 
2440 語句描述:使用InsertOnSubmit方法將新類別添加到Categories 表中,並將新Product對象添加到與此新Category有外鍵關係的Products表中。調用SubmitChanges將這些新對象及其關係保存到數據庫。
2441 
2442  
2443 
2444 3.多對多關係
2445  
2446 
2447 說明:在多對多關係中,咱們須要依次提交。
2448 
2449  
2450 
2451 var newEmployee = new Employee
2452 
2453 {
2454 
2455   FirstName = "Kira",
2456 
2457   LastName = "Smith"
2458 
2459 };
2460 
2461 var newTerritory = new Territory
2462 
2463 {
2464 
2465   TerritoryID = "12345",
2466 
2467   TerritoryDescription = "Anytown",
2468 
2469   Region = db.Regions.First()
2470 
2471 };
2472 
2473 var newEmployeeTerritory = newEmployeeTerritory
2474 
2475 {
2476 
2477    Employee = newEmployee,
2478 
2479   Territory = newTerritory
2480 
2481 };
2482 
2483 db.Employees.InsertOnSubmit(newEmployee);
2484 
2485 db.Territories.InsertOnSubmit(newTerritory);
2486 
2487 db.EmployeeTerritories.InsertOnSubmit(newEmployeeTerritory);
2488 
2489 db.SubmitChanges();
2490 
2491  
2492 
2493 語句描述:使用InsertOnSubmit方法將新僱員添加到Employees 表中,將新Territory添加到Territories表中,並將新 EmployeeTerritory對象添加到與此新Employee對象和新Territory對象有外鍵關係的EmployeeTerritories表中。調用SubmitChanges將這些新對象及其關係保持到數據庫。
2494 
2495  
2496 
2497 4.使用動態CUD重寫(Overrideusing Dynamic CUD)
2498  
2499 
2500 說明:CUD就是Create、Update、Delete的縮寫。下面的例子就是新建一個ID(主鍵) 爲32的Region,不考慮數據庫中有沒有ID爲32的數據,若是有則替換原來的數據,沒有則插入。
2501 
2502  
2503 
2504 Region nwRegion = new Region()
2505 
2506 {
2507 
2508   RegionID = 32,
2509 
2510   RegionDescription = "Rainy"
2511 
2512 };
2513 
2514 db.Regions.InsertOnSubmit(nwRegion);
2515 
2516 db.SubmitChanges ();
2517 
2518  
2519 
2520 語句描述:使用DataContext提供的分部方法InsertRegion插入一個區域。對SubmitChanges 的調用調用InsertRegion 重寫,後者使用動態CUD運行Linq To SQL生成的默認SQL查詢。
2521 
2522  
2523 
2524 LINQ to SQL語句(11)之Update
2525 更新(Update)
2526  
2527 
2528 說明:更新操做,先獲取對象,進行修改操做以後,直接調用SubmitChanges()方法便可提交。注意,這裏是在同一個DataContext中,對於不一樣的DataContex看下面的講解。
2529 
2530  
2531 
2532 1.簡單形式
2533 Customer cust =
2534 
2535   db.Customers.First(c => c.CustomerID == "ALFKI");
2536 
2537 cust.ContactTitle = "VicePresident";
2538 
2539 db.SubmitChanges();
2540 
2541  
2542 
2543 語句描述:使用 SubmitChanges將對檢索到的一個Customer對象作出的更新保持回數據庫。
2544 
2545  
2546 
2547 2.多項更改
2548 var q = from p in db.Products
2549 
2550      where p.CategoryID == 1
2551 
2552     select p;
2553 
2554 foreach (var p in q)
2555 
2556 {
2557 
2558   p.UnitPrice += 1.00M;
2559 
2560 }
2561 
2562 db.SubmitChanges ();
2563 
2564  
2565 
2566 語句描述:使用SubmitChanges將對檢索到的進行的更新保持回數據庫。
2567 
2568  
2569 
2570 LINQ to SQL語句(12)之Delete和使用Attach
2571 刪除(Delete)1.簡單形式
2572  
2573 
2574 說明:調用DeleteOnSubmit方法便可。
2575 
2576  
2577 
2578 OrderDetail orderDetail =
2579 
2580    db.OrderDetails.First
2581 
2582   (c => c.OrderID == 10255 && c.ProductID == 36);
2583 
2584 db.OrderDetails.DeleteOnSubmit(orderDetail);
2585 
2586 db.SubmitChanges();
2587 
2588  
2589 
2590 語句描述:使用 DeleteOnSubmit方法從OrderDetail 表中刪除OrderDetail對象。調用 SubmitChanges 將此刪除保持到數據庫。
2591 
2592  
2593 
2594 2.一對多關係
2595  
2596 
2597 說明:Order 與OrderDetail是一對多關係,首先DeleteOnSubmit其OrderDetail(多端),其次 DeleteOnSubmit其Order(一端)。由於一端是主鍵。
2598 
2599  
2600 
2601 var orderDetails =
2602 
2603   from o in db.OrderDetails
2604 
2605   where o.Order.CustomerID == "WARTH" &&
2606 
2607    o.Order.EmployeeID == 3
2608 
2609   select o;
2610 
2611 var order =
2612 
2613    (from o in db.Orders
2614 
2615    where o.CustomerID == "WARTH" && o.EmployeeID ==3
2616 
2617    select o).First();
2618 
2619 foreach (OrderDetail od in orderDetails)
2620 
2621 {
2622 
2623    db.OrderDetails.DeleteOnSubmit(od);
2624 
2625 }
2626 
2627 db.Orders.DeleteOnSubmit(order);
2628 
2629 db.SubmitChanges();
2630 
2631  
2632 
2633 語句描述語句描述:使用DeleteOnSubmit方法從Order 和Order Details表中刪除Order和Order Detail對象。首先從Order Details刪除,而後從Orders刪除。調用SubmitChanges將此刪除保持到數據庫。
2634 
2635  
2636 
2637 3.推理刪除(Inferred Delete)
2638  
2639 
2640 說明:Order與OrderDetail是一對多關係,在上面的例子,咱們所有刪除CustomerID爲WARTH和EmployeeID爲3 的數據,那麼咱們不須所有刪除呢?例如Order的OrderID爲10248的OrderDetail有不少,可是咱們只要刪除 ProductID爲11的OrderDetail。這時就用Remove方法。
2641 
2642  
2643 
2644 Order order = db.Orders.First(x =>x.OrderID == 10248);
2645 
2646 OrderDetail od =
2647 
2648   order.OrderDetails.First(d => d.ProductID == 11);
2649 
2650 order.OrderDetails.Remove(od);
2651 
2652 db.SubmitChanges();
2653 
2654  
2655 
2656 語句描述語句描述:這個例子說明在實體對象的引用實體將該對象從其EntitySet 中移除時,推理刪除如何致使在該對象上發生實際的刪除操做。僅當實體的關聯映射將DeleteOnNull設置爲true且CanBeNull 爲false 時,纔會發生推理刪除行爲。
2657 
2658  
2659 
2660 使用Attach更新(Updatewith Attach)
2661  
2662 
2663 說明:在對於在不一樣的 DataContext之間,使用Attach方法來更新數據。例如在一個名爲tempdb的 NorthwindDataContext中,查詢出Customer和Order,在另外一個 NorthwindDataContext中,Customer的地址更新爲123 First Ave,Order的 CustomerID 更新爲CHOPS。
2664 
2665  
2666 
2667 //一般,經過從其餘層反序列化 XML 來獲取要附加的實體
2668 
2669 //不支持將實體從一個DataContext附加到另外一個DataContext
2670 
2671 //所以若要複製反序列化實體的操做,將在此處從新建立這 些實體
2672 
2673 Customer c1;
2674 
2675 List<Order> deserializedOrders = newList<Order>();
2676 
2677 Customer deserializedC1;
2678 
2679 using (NorthwindDataContext tempdb = newNorthwindDataContext())
2680 
2681 {
2682 
2683   c1 = tempdb.Customers.Single(c => c.CustomerID =="ALFKI");
2684 
2685   deserializedC1 = new Customer
2686 
2687    {
2688 
2689     Address = c1.Address,
2690 
2691     City = c1.City,
2692 
2693     CompanyName = c1.CompanyName,
2694 
2695     ContactName = c1.ContactName,
2696 
2697     ContactTitle = c1.ContactTitle,
2698 
2699     Country = c1.Country,
2700 
2701     CustomerID = c1.CustomerID,
2702 
2703     Fax = c1.Fax,
2704 
2705     Phone = c1.Phone,
2706 
2707      PostalCode = c1.PostalCode,
2708 
2709     Region = c1.Region
2710 
2711   };
2712 
2713   Customer tempcust =
2714 
2715      tempdb.Customers.Single(c => c.CustomerID == "ANTON");
2716 
2717   foreach (Order o in tempcust.Orders)
2718 
2719   {
2720 
2721      deserializedOrders.Add(new Order
2722 
2723     {
2724 
2725        CustomerID = o.CustomerID,
2726 
2727       EmployeeID = o.EmployeeID,
2728 
2729       Freight = o.Freight,
2730 
2731        OrderDate = o.OrderDate,
2732 
2733       OrderID = o.OrderID,
2734 
2735       RequiredDate = o.RequiredDate,
2736 
2737       ShipAddress = o.ShipAddress,
2738 
2739       ShipCity = o.ShipCity,
2740 
2741       ShipName = o.ShipName,
2742 
2743       ShipCountry = o.ShipCountry,
2744 
2745       ShippedDate = o.ShippedDate,
2746 
2747       ShipPostalCode = o.ShipPostalCode,
2748 
2749       ShipRegion = o.ShipRegion,
2750 
2751       ShipVia = o.ShipVia
2752 
2753     });
2754 
2755   }
2756 
2757 }
2758 
2759 using (NorthwindDataContext db2 = newNorthwindDataContext())
2760 
2761 {
2762 
2763   //將第一個實體附加到當前數據上下文,以跟蹤更改
2764 
2765   //對Customer更新,不能寫錯
2766 
2767    db2.Customers.Attach(deserializedC1);
2768 
2769   //更改所跟蹤的實體
2770 
2771   deserializedC1.Address = "123 First Ave";
2772 
2773   // 附加訂單列表中的全部實體
2774 
2775   db2.Orders.AttachAll (deserializedOrders);
2776 
2777   //將訂單更新爲屬於其餘客戶
2778 
2779    foreach (Order o in deserializedOrders)
2780 
2781   {
2782 
2783      o.CustomerID = "CHOPS";
2784 
2785   }
2786 
2787   //在當前數據上下文中提交更改
2788 
2789   db2.SubmitChanges();
2790 
2791 }
2792 
2793  
2794 
2795 語句描述:從另外一個層中獲取實體,使用Attach和AttachAll將反序列化後的實體附加到數據上下文,而後更新實體。更改被提交到數據庫。
2796 
2797  
2798 
2799 使用Attach更新和刪除(Update and Delete with Attach)
2800 
2801  
2802 
2803 說明:在不一樣的DataContext中,實現插入、更新、刪除。看下面的一個例子:
2804 
2805  
2806 
2807 //一般,經過從其餘層 反序列化XML獲取要附加的實體
2808 
2809 //此示例使用 LoadWith 在一個查詢中預 先加載客戶和訂單,
2810 
2811 //並禁用延遲加載
2812 
2813 Customer cust = null;
2814 
2815 using (NorthwindDataContext tempdb = newNorthwindDataContext())
2816 
2817 {
2818 
2819   DataLoadOptions shape = new DataLoadOptions();
2820 
2821    shape.LoadWith<Customer>(c => c.Orders);
2822 
2823   //加載第一個客戶實體及其訂單
2824 
2825   tempdb.LoadOptions = shape;
2826 
2827    tempdb.DeferredLoadingEnabled = false;
2828 
2829   cust = tempdb.Customers.First(x => x.CustomerID =="ALFKI");
2830 
2831 }
2832 
2833 Order orderA = cust.Orders.First();
2834 
2835 Order orderB = cust.Orders.First(x =>x.OrderID > orderA.OrderID);
2836 
2837 using (NorthwindDataContext db2 = newNorthwindDataContext())
2838 
2839 {
2840 
2841   //將第一個實體附加到當前數據上下文,以跟蹤更改
2842 
2843    db2.Customers.Attach(cust);
2844 
2845   //附加相關訂單以進行跟蹤; 不然將在提交時插入它們
2846 
2847   db2.Orders.AttachAll(cust.Orders.ToList ());
2848 
2849   //更新客戶的Phone.
2850 
2851   cust.Phone = "2345 5436";
2852 
2853   //更新第一個訂單OrderA的ShipCity.
2854 
2855    orderA.ShipCity = "Redmond";
2856 
2857   //移除第二個訂單 OrderB.
2858 
2859   cust.Orders.Remove(orderB);
2860 
2861   //添加一個新的訂單Order到客戶Customer中.
2862 
2863   Order orderC = new Order() { ShipCity = "New York" };
2864 
2865   cust.Orders.Add (orderC);
2866 
2867   //提交執行
2868 
2869   db2.SubmitChanges();
2870 
2871 }
2872 
2873  
2874 
2875 語句描述:從一個上下文提取實體,並使用 Attach 和 AttachAll 附加來自其餘上下文的實體,而後更新這兩個實體,刪除一個實體,添加另外一個實體。更改被提交到數據庫。
2876 
2877  
2878 
2879 LINQ to SQL語句(13)之開放式併發控制和事務
2880 Simultaneous Changes開放式併發控制
2881  
2882 
2883 下表介紹 LINQ to SQL 文檔中涉及開放式併發的術語:
2884 
2885  
2886 
2887 術語說明
2888 
2889 併發兩個或更多用戶同時嘗試更新同一數據庫行的情形。
2890 
2891 併發衝突兩個或更多用戶同時嘗試向一行的一列或多列提交衝突值的情形。
2892 
2893 併發控制用於解決併發衝突的技術。
2894 
2895 開放式併發控制先調查其餘事務是否已更改了行中的值,再容許提交更改的技術。相比之下,保守式併發控制則是經過鎖定記錄來避免發生併發衝突。之因此稱做開放式控制,是由於它將一個事務干擾另外一事務視爲不太可能發生。
2896 
2897 衝突解決經過從新查詢數據庫刷新出現衝突的項,而後協調差別的過程。刷新對象時,LINQ to SQL 更改跟蹤器會保留如下數據:最初從數據庫獲取並用於更新檢查的值經過後續查詢得到的新數據庫值。 LINQ to SQL 隨後會肯定相應對象是否發生衝突(即它的一個或多個成員值是否已發生更改)。若是此對象發生衝突,LINQ to SQL 下一步會肯定它的哪些成員發生衝突。LINQ to SQL 發現的任何成員衝突都會添加到衝突列表中。
2898 
2899  
2900 
2901  
2902 
2903 在 LINQ to SQL 對象模型中,當如下兩個條件都獲得知足時,就會發生「開放式併發衝突」:客戶端嘗試向數據庫提交更改;數據庫中的一個或多個更新檢查值自客戶端上次讀取它們以來已獲得更新。此衝突的解決過程包括查明對象的哪些成員發生衝突,而後決定您但願如何進行處理。
2904 
2905  
2906 
2907 開放式併發(Optimistic Concurrency)
2908  
2909 
2910 說明:這個例子中在你讀取數據以前,另一個用戶已經修改並提交更新了這個數據,因此不會出現衝突。
2911 
2912  
2913 
2914 //咱們打開一個新的鏈接來模擬另一個用戶
2915 
2916 NorthwindDataContext otherUser_db = newNorthwindDataContext();
2917 
2918 var otherUser_product =
2919 
2920   otherUser_db.Products.First(p => p.ProductID == 1);
2921 
2922 otherUser_product.UnitPrice = 999.99M;
2923 
2924 otherUser_db.SubmitChanges();
2925 
2926 //咱們當前鏈接
2927 
2928 var product = db.Products.First(p =>p.ProductID == 1);
2929 
2930 product.UnitPrice = 777.77M;
2931 
2932 try
2933 
2934 {
2935 
2936   db.SubmitChanges();//當前鏈接執行成功
2937 
2938 }
2939 
2940 catch (ChangeConflictException)
2941 
2942 {
2943 
2944 }
2945 
2946  
2947 
2948 說明:咱們讀取數據以後,另一個用戶獲取並提交更新了這個數據,這時,咱們更新這個數據時,引發了一個併發衝突。系統發生回滾,容許你能夠從數據庫檢索新更新的數據,並決定如何繼續進行您本身的更新。
2949 
2950  
2951 
2952 //當前 用戶
2953 
2954 var product = db.Products.First(p =>p.ProductID == 1);
2955 
2956 //咱們打開一個新的鏈接來模擬另一個用戶
2957 
2958 NorthwindDataContext otherUser_db = newNorthwindDataContext() ;
2959 
2960 var otherUser_product =
2961 
2962   otherUser_db.Products.First(p => p.ProductID == 1);
2963 
2964 otherUser_product.UnitPrice = 999.99M;
2965 
2966 otherUser_db.SubmitChanges();
2967 
2968 //當前用戶修改
2969 
2970 product.UnitPrice = 777.77M;
2971 
2972 try
2973 
2974 {
2975 
2976    db.SubmitChanges();
2977 
2978 }
2979 
2980 catch (ChangeConflictException)
2981 
2982 {
2983 
2984   //發生異常!
2985 
2986 }
2987 
2988  
2989 
2990 Transactions事務
2991 
2992  
2993 
2994 LINQto SQL 支持三種事務模型,分別是:
2995 
2996  
2997 
2998 顯式本地事務:調用 SubmitChanges 時,若是 Transaction 屬性設置爲事務,則在同一事務的上下文中執行 SubmitChanges 調用。成功執行事務後,要由您來提交或回滾事務。與事務對應的鏈接必須與用於構造 DataContext 的鏈接匹配。若是使用其餘鏈接,則會引起異常。
2999 
3000  
3001 
3002 顯式可分發事務:能夠在當前 Transaction 的做用域中調用 LINQ to SQL API(包括但不限於 SubmitChanges)。LINQ to SQL 檢測到調用是在事務的做用域內,於是不會建立新的事務。在這種狀況下, <token>vbtecdlinq</token> 還會避免關閉鏈接。您能夠在此類事 務的上下文中執行查詢和SubmitChanges 操做。
3003 
3004  
3005 
3006 隱式事務:當您調用 SubmitChanges 時,LINQ to SQL 會檢查此調用是否在 Transaction 的做用域內或者 Transaction 屬性是否設置爲由用戶啓動的本地事務。若是這兩個事務它均未找到,則 LINQ to SQL 啓動本地事務,並使用此事務執行所生成的 SQL 命令。當全部 SQL 命令均已成功執行完畢時,LINQ to SQL 提交本地事務並返回。
3007 
3008  
3009 
3010 1.Implicit(隱式)
3011  
3012 
3013 說明:這個例子在執行SubmitChanges ()操做時,隱式地使用了事務。由於在更新2種產品的庫存數量時,第二個產品庫存數量爲負數了,違反了服務器上的 CHECK 約束。這致使了更新產品所有失敗了,系統回滾到這個操做的初始狀態。
3014 
3015 try
3016 
3017 {
3018 
3019   Product prod1 = db.Products.First(p => p.ProductID == 4);
3020 
3021   Product prod2 = db.Products.First(p => p.ProductID == 5);
3022 
3023    prod1.UnitsInStock -= 3;
3024 
3025   prod2.UnitsInStock -= 5;//錯誤:庫存 數量的單位不能是負數
3026 
3027   //要麼所有成功要麼所有失敗
3028 
3029    db.SubmitChanges();
3030 
3031 }
3032 
3033 catch (System.Data.SqlClient.SqlExceptione)
3034 
3035 {
3036 
3037   //執行異常處理
3038 
3039 }
3040 
3041  
3042 
3043 2.Explicit(顯式)
3044  
3045 
3046 說明:這個例子使用顯式事務。經過在事務中加入對數據的讀取以防止出現開放式併發異常,顯式事務能夠提供更多的保護。如同上一個查詢中,更新 prod2 的 UnitsInStock 字段將使該字段爲負值,而這違反了數據庫中的 CHECK 約束。這致使更新這兩個產品的事務失敗,此時將回滾全部更改。
3047 
3048  
3049 
3050 using (TransactionScope ts = new TransactionScope())
3051 
3052 {
3053 
3054   try
3055 
3056   {
3057 
3058      Product prod1 = db.Products.First(p => p.ProductID == 4);
3059 
3060     Product prod2 = db.Products.First(p => p.ProductID == 5);
3061 
3062     prod1.UnitsInStock -= 3;
3063 
3064     prod2.UnitsInStock -= 5;//錯誤:庫存數量的單位不能是負數
3065 
3066     db.SubmitChanges();
3067 
3068   }
3069 
3070   catch (System.Data.SqlClient.SqlException e)
3071 
3072   {
3073 
3074     //執行異常處理
3075 
3076   }
3077 
3078 }
3079 
3080  
3081 
3082 LINQ to SQL語句(14)之Null語義和DateTime
3083 Null語義
3084  
3085 
3086 說明:下面第一個例子說明查詢ReportsToEmployee爲null的僱員。第二個例子使用Nullable<T>.HasValue查詢僱員,其結果與第一個例 子相同。在第三個例子中,使用Nullable<T>.Value來返回ReportsToEmployee不爲null的僱員的ReportsTo的值。
3087 
3088  
3089 
3090 1.Null
3091  
3092 
3093 查找不隸屬於另外一個僱員的全部僱員:
3094 
3095  
3096 
3097 var q =
3098 
3099   from e in db.Employees
3100 
3101   where e.ReportsToEmployee == null
3102 
3103    select e;
3104 
3105 2.Nullable<T>.HasValue
3106  
3107 
3108 查找不隸屬於另外一個僱員的全部僱員:
3109 
3110  
3111 
3112 var q =
3113 
3114   from e in db.Employees
3115 
3116   where !e.ReportsTo.HasValue
3117 
3118   select e;
3119 
3120 3.Nullable<T>.Value
3121 
3122  
3123 
3124 返回前者的EmployeeID 編號。請注意 .Value 爲可選:
3125 
3126  
3127 
3128 var q =
3129 
3130   from e in db.Employees
3131 
3132   where e.ReportsTo.HasValue
3133 
3134   select new
3135 
3136   {
3137 
3138     e.FirstName,
3139 
3140     e.LastName,
3141 
3142     ReportsTo = e.ReportsTo.Value
3143 
3144   };
3145 
3146 日期函數
3147  
3148 
3149 LINQ to SQL支持如下 DateTime方法。可是,SQLServer和CLR的DateTime類型在範圍和計時週期精度上不一樣,以下表。
3150 
3151  
3152 
3153 類型最小值 最大 值 計時週期
3154 
3155 System.DateTime 00011199991231100 毫微秒(0.0000001秒)
3156 
3157 T-SQL DateTime 175311999912313.33… 毫秒(0.0033333 秒)
3158 
3159 T-SQL SmallDateTime 1900112079661 分鐘(60 秒)
3160 
3161  
3162 
3163  
3164 
3165 CLR DateTime 類型與SQL Server類型相比,前者範圍更 大、精度更高。所以來自SQLServer的數據用CLR類型表示時,毫不會損失量值或精度。但若是反過來的話,則範圍可能會減少,精度可能會下降;SQL Server 日期不存在TimeZone概念,而在CLR中支持這個功能。
3166 
3167  
3168 
3169 咱們在LINQ to SQL查詢使用以當地時間、UTC 或固定時間要本身執行轉換。
3170 
3171  
3172 
3173 下面用三個實例說明一下。
3174 
3175  
3176 
3177 1.DateTime.Year
3178 var q =
3179 
3180   from o in db.Orders
3181 
3182   where o.OrderDate.Value.Year == 1997
3183 
3184    select o;
3185 
3186  
3187 
3188 語句描述:這個例子使用DateTime 的Year 屬性查找1997 年下的訂單。
3189 
3190  
3191 
3192 2.DateTime.Month
3193 var q =
3194 
3195   from o in db.Orders
3196 
3197   where o.OrderDate.Value.Month == 12
3198 
3199   select o;
3200 
3201  
3202 
3203 語句描述:這個例子使用DateTime的Month屬性查找十二月下的訂單。
3204 
3205  
3206 
3207 3.DateTime.Day
3208 var q =
3209 
3210   from o in db.Orders
3211 
3212   where o.OrderDate.Value.Day == 31
3213 
3214   select o;
3215 
3216  
3217 
3218 語句描述:這個例子使用DateTime的Day屬性查找某月 31 日下的訂單。
3219 
3220  
3221 
3222  
3223 
3224 LINQ to SQL語句(15)之String
3225 字符串(String)
3226  
3227 
3228 LINQ to SQL支持如下String方法。可是不一樣的是默認 狀況下System.String方法區分大小寫。而SQL則不區分大小寫。
3229 
3230  
3231 
3232 1.字符串串聯(StringConcatenation)
3233 var q =
3234 
3235   from c in db.Customers
3236 
3237   select new
3238 
3239   {
3240 
3241      c.CustomerID,
3242 
3243     Location = c.City + ", " + c.Country
3244 
3245   };
3246 
3247  
3248 
3249 語句描述:這個例子使用+運算符在造成經計算得出的客戶Location值過程當中將字符串字段和字符串串聯在一塊兒。
3250 
3251  
3252 
3253 2.String.Length
3254 var q =
3255 
3256   from p in db.Products
3257 
3258   where p.ProductName.Length < 10
3259 
3260   select p;
3261 
3262  
3263 
3264 語句描述:這個例子使用Length屬性查找名稱短於10個字符的全部產品。
3265 
3266  
3267 
3268 3.String.Contains(substring)
3269 var q =
3270 
3271   from c in db.Customers
3272 
3273   where c.ContactName.Contains ("Anders")
3274 
3275   select c;
3276 
3277  
3278 
3279 語句描述:這個例子使用Contains方法查找全部其聯繫人姓名中包含「Anders」的客戶。
3280 
3281  
3282 
3283 4.String.IndexOf(substring)
3284 var q =
3285 
3286   from c in db.Customers
3287 
3288   select new
3289 
3290   {
3291 
3292      c.ContactName,
3293 
3294     SpacePos = c.ContactName.IndexOf(" ")
3295 
3296   };
3297 
3298  
3299 
3300 語句描述:這個例子使用IndexOf方法查找每一個客戶聯繫人姓名中出現第一個空格的位置。
3301 
3302  
3303 
3304 5.String.StartsWith (prefix)
3305 var q =
3306 
3307   from c in db.Customers
3308 
3309   where c.ContactName.StartsWith("Maria")
3310 
3311   select c;
3312 
3313  
3314 
3315 語句描述:這個例子使用StartsWith方法查找聯繫人姓名以「Maria」開頭的客戶。
3316 
3317  
3318 
3319 6.String.EndsWith(suffix)
3320 var q =
3321 
3322   from c in db.Customers
3323 
3324   where c.ContactName.EndsWith("Anders")
3325 
3326   select c;
3327 
3328  
3329 
3330 語句描述:這個例子使用EndsWith方法查找聯繫人姓名以「Anders」結尾的客戶。
3331 
3332  
3333 
3334 7.String.Substring(start)
3335 var q =
3336 
3337   from p in db.Products
3338 
3339   select p.ProductName.Substring(3);
3340 
3341  
3342 
3343 語句描述:這個例子使用Substring方法返回產品名稱中從第四個字母開始的部分。
3344 
3345  
3346 
3347 8.String.Substring (start, length)
3348 var q =
3349 
3350   from e in db.Employees
3351 
3352    where e.HomePhone.Substring(6, 3) == "555"
3353 
3354   select e;
3355 
3356  
3357 
3358 語句描述:這個例子使用Substring方法查找家庭電話號碼第七位到第九位是「555」的僱員。
3359 
3360  
3361 
3362 9.String.ToUpper()
3363 var q =
3364 
3365   from e in db.Employees
3366 
3367   select new
3368 
3369   {
3370 
3371     LastName = e.LastName.ToUpper(),
3372 
3373     e.FirstName
3374 
3375   };
3376 
3377  
3378 
3379 語句描述:這個例子使用ToUpper方法返回姓氏已轉換爲大寫的僱員姓名。
3380 
3381  
3382 
3383 10.String.ToLower()
3384 var q =
3385 
3386   from c in db.Categories
3387 
3388   select c.CategoryName.ToLower();
3389 
3390  
3391 
3392 語句描述:這個例子使用ToLower方法返回已轉換爲小寫的類別名稱。
3393 
3394  
3395 
3396 11.String.Trim()
3397 var q =
3398 
3399   from e in db.Employees
3400 
3401   select e.HomePhone.Substring(0, 5).Trim ();
3402 
3403  
3404 
3405 語句描述:這個例子使用Trim方法返回僱員家庭電話號碼的前五位,並移除前導和尾隨空格。
3406 
3407  
3408 
3409 12.String.Insert(pos, str)
3410 var q =
3411 
3412   from e in db.Employees
3413 
3414   where e.HomePhone.Substring(4, 1) == ")"
3415 
3416   select e.HomePhone.Insert(5, ":");
3417 
3418  
3419 
3420 語句描述:這個例子使用 Insert方法返回第五位爲 ) 的僱員電話號碼的序列,並在 ) 後面插入一個 :。
3421 
3422  
3423 
3424 13.String.Remove(start)
3425 var q =
3426 
3427   from e in db.Employees
3428 
3429   where e.HomePhone.Substring(4, 1) == ") "
3430 
3431   select e.HomePhone.Remove(9);
3432 
3433  
3434 
3435 語句描述:這個例子使用Remove方法返回第五位爲 ) 的僱員電話號碼的序列,並移除從第十個字符開始的全部字符。
3436 
3437  
3438 
3439 14.String.Remove(start, length)
3440 var q =
3441 
3442   from e in db.Employees
3443 
3444   where e.HomePhone.Substring(4, 1) == ")"
3445 
3446   select e.HomePhone.Remove(0, 6);
3447 
3448  
3449 
3450 語句描述:這個例子使用Remove方法返回第五位爲 ) 的僱員電話號碼的序列,並移除前六個字符。
3451 
3452  
3453 
3454 15.String.Replace(find, replace)
3455 var q =
3456 
3457   from s in db.Suppliers
3458 
3459   select new
3460 
3461   {
3462 
3463      s.CompanyName,
3464 
3465     Country = s.Country
3466 
3467     .Replace ("UK", "United Kingdom")
3468 
3469     .Replace ("USA", "United States of America")
3470 
3471   };
3472 
3473  
3474 
3475 語句描述:這個例子使用 Replace 方法返回 Country 字段中UK 被替換爲 United Kingdom 以及USA 被替換爲 United States of America 的供 應商信息。
3476 
3477  
3478 
3479  
3480 
3481 LINQ to SQL語句(16)之對象標識
3482 對象標識
3483  
3484 
3485 運行庫中的對象具備惟一標識。引用同一對象的兩個變量其實是引用此對象的同一實例。你更改一個變量後,能夠經過另外一個變量看到這些更改。
3486 
3487  
3488 
3489 關係數據庫表中的行不具備惟一標識。因爲每一行都具備惟一的主鍵,所以任何兩行都不會共用同一鍵值。
3490 
3491  
3492 
3493 實際上,一般咱們是將數據從數據庫中提取出來放入另外一層中,應用程序在該層對數據進行處理。這就是 LINQ to SQL 支持的模型。將數據做爲行從數據庫中提取出來時,你不指望表示相同數據的兩行實際上對應於相同的行實例。若是您查詢特定客戶兩次,您將得到兩行數據。每一行包含相同的信息。
3494 
3495  
3496 
3497 對於對象。你指望在你反覆向 DataContext 索取相同的信息時,它實際上會爲你提供同一對象實例。你將它們設計爲層次結構或關係圖。你但願像檢索實物同樣檢索它們,而不但願僅僅由於你屢次索要同一內容而收到大量的複製實例。
3498 
3499  
3500 
3501 在 LINQ to SQL 中, DataContext 管理對象標識。只要你從數據庫中檢索新行,該行就會由其主鍵記錄到標識表中,而且會建立一個新的對象。只要您檢索該行,就會將原始對象實例傳遞迴應用程序。經過這種方式,DataContext 將數據庫看到的標識(即主鍵)的概念轉換成相應語言看到的標識(即實例)的概念。應用程序只看處處於第一次檢索時的狀態的對象。新數據若是不一樣,則會被丟棄。
3502 
3503  
3504 
3505 LINQ to SQL 使用此方法來管理本地對象的完整性,以支持開放式更新。因爲在最初建立對象 後惟一發生的更改是由應用程序作出的,所以應用程序的意向是很明確的。若是在中間階段外部某一方作了更改,則在調用 SubmitChanges() 時會識別出這些更改。
3506 
3507  
3508 
3509 以上來自MSDN,的確,看了有點「正規」,下面我用兩個例子說明一下。
3510 
3511  
3512 
3513 對象緩存
3514  
3515 
3516 在第一個示例中,若是咱們執行同一查詢兩次,則每次都會收到對內存中同一對象的引用。很明顯,cust1和cust2是同一個對象引用。
3517 
3518  
3519 
3520 Customer cust1 = db.Customers.First(c =>c.CustomerID == "BONAP");
3521 
3522 Customer cust2 = db.Customers.First(c =>c.CustomerID == "BONAP");
3523 
3524  
3525 
3526 下面的示例中,若是您執行返回數據庫中同一行的不一樣查詢,則您每次都會收到對內存中同一對象的引用。cust1和cust2是同一個對象引用,可是數據庫查詢了兩次。
3527 
3528  
3529 
3530 Customer cust1 = db.Customers.First(c =>c.CustomerID == "BONAP");
3531 
3532 Customer cust2 = (
3533 
3534   from o in db.Orders
3535 
3536   where o.Customer.CustomerID == "BONAP"
3537 
3538   select o )
3539 
3540   .First()
3541 
3542   .Customer;
3543 
3544  
3545 
3546 LINQ to SQL語句(17)之對象加載
3547 對象加載延遲加載
3548  
3549 
3550 在查詢某對象時,實際上你只查詢該對象。不會同時自動獲取這個對象。這就是延遲加載。
3551 
3552  
3553 
3554 例如,您可能須要查看客戶數據和訂單數據。你最初不必定須要檢索與每一個客戶有關的全部訂單數據。其優勢是你可使用延遲加載將額外信息的檢索操做延遲到你確實須要檢索它們時再進行。請看下面的示例:檢索出來CustomerID,就根據這個ID查詢出OrderID。
3555 
3556  
3557 
3558 var custs =
3559 
3560    from c in db.Customers
3561 
3562    where c.City == "Sao Paulo"
3563 
3564    select c;
3565 
3566 //上面 的查詢句法不會致使語句當即執行,僅僅是一個描述性的語句,
3567 
3568 只有須要的時候纔會執行它
3569 
3570 foreach (var cust in custs)
3571 
3572 {
3573 
3574    foreach (var ord in cust.Orders)
3575 
3576   {
3577 
3578     //同時查看客戶數據和訂單數據
3579 
3580   }
3581 
3582 }
3583 
3584  
3585 
3586 語句描述:原始查詢未請求數據,在所檢索到各個對象的連接中導航如何能致使觸發對數據庫的新查詢。
3587 
3588  
3589 
3590 預先加載:LoadWith 方法
3591  
3592 
3593 你若是想要同時查詢出一些對象的集合的方法。LINQ to SQL 提供了 DataLoadOptions用於當即加載對象。方法包括:
3594 
3595  
3596 
3597 LoadWith 方法,用於當即加載與主目標相關的數據。
3598 
3599  
3600 
3601 AssociateWith 方法,用於篩選爲特定關係檢索到的對象。
3602 
3603  
3604 
3605 使用 LoadWith方法指定應同時檢索與主目標相關的哪些數據。例如,若是你知道你須要有關客戶的訂單的信息,則可使用 LoadWith 來確保在檢索客戶信息的同時檢索訂單信息。使用此方法可僅訪問一次數據庫,但同時獲取兩組信息。
3606 
3607  
3608 
3609 在下面的示例中,咱們經過設置DataLoadOptions,來指示DataContext 在加載Customers的同時把對應的Orders一塊兒加載,在執行查詢時會檢索位於Sao Paulo的全部 Customers 的全部 Orders。這樣一來,連續訪問 Customer 對象的 Orders 屬性不會觸發新的數據庫查詢。在執行時生成的SQL語句使用了左鏈接。
3610 
3611  
3612 
3613 NorthwindDataContext db = newNorthwindDataContext ();
3614 
3615 DataLoadOptions ds = new DataLoadOptions();
3616 
3617 ds.LoadWith<Customer>(p =>p.Orders);
3618 
3619 db.LoadOptions = ds;
3620 
3621 var custs = (
3622 
3623    from c in db2.Customers
3624 
3625    where c.City == "Sao Paulo"
3626 
3627    select c);
3628 
3629 foreach (var cust in custs)
3630 
3631 {
3632 
3633   foreach (var ord in cust.Orders)
3634 
3635   {
3636 
3637     Console.WriteLine ("CustomerID {0} has an OrderID {1}.",
3638 
3639        cust.CustomerID,
3640 
3641       ord.OrderID);
3642 
3643   }
3644 
3645 }
3646 
3647  
3648 
3649 語句描述:在原始查詢過程當中使用 LoadWith 請求相關數據,以便稍後在檢索到的各個對象中導航時不須要對數據庫進行額外的往返。
3650 
3651  
3652 
3653 LINQ to SQL語句(18)之運算符轉換
3654 運算符轉換
3655 
3656 1.AsEnumerable:將類型轉換爲泛型 IEnumerable
3657  
3658 
3659 使用 AsEnumerable<TSource> 可返回類型化爲泛型 IEnumerable的參數。在 此示例中,LINQ toSQL(使用默認泛型 Query)會嘗試將查詢轉換爲 SQL 並在服務器上執行。但 where 子句引用用戶定義的客戶端方法 (isValidProduct),此方法沒法轉換爲 SQL。
3660 
3661  
3662 
3663 解決方法是指定 where 的客戶端泛型 IEnumerable<T> 實現以替換泛型 IQueryable<T>。可經過調用 AsEnumerable<TSource>運算符來執行此操做。
3664 
3665  
3666 
3667 var q =
3668 
3669   from p in db.Products.AsEnumerable()
3670 
3671   where isValidProduct(p)
3672 
3673   select p;
3674 
3675  
3676 
3677 語句描述:這個例子就是使用AsEnumerable以便使用Where的客戶端IEnumerable實現,而不是默認的 IQueryable將在服務器上轉換爲SQL並執行的默認Query<T>實現。這頗有必要,由於Where子句引用了用戶定義的客戶端方法isValidProduct,該方法不能轉換爲SQL。
3678 
3679  
3680 
3681 2.ToArray:將序列轉換爲數組
3682  
3683 
3684 使用 ToArray <TSource>可從序列建立數組。
3685 
3686  
3687 
3688 var q =
3689 
3690   from c in db.Customers
3691 
3692   where c.City == "London"
3693 
3694    select c;
3695 
3696 Customer[] qArray = q.ToArray();
3697 
3698  
3699 
3700 語句描述:這個例子使用 ToArray 將查詢直接計算爲數組。
3701 
3702  
3703 
3704 3.ToList:將序列轉換爲泛型列表
3705  
3706 
3707 使用 ToList<TSource>可從序列建立泛型列表。下面的示例使用 ToList<TSource>直接將查詢的計算結果放入泛型 List<T>3708 
3709  
3710 
3711 var q =
3712 
3713   from e in db.Employees
3714 
3715   where e.HireDate >= new DateTime(1994, 1, 1)
3716 
3717   select e;
3718 
3719 List<Employee> qList = q.ToList();
3720 
3721 4.ToDictionary:將序列轉化爲字典
3722  
3723 
3724 使用Enumerable.ToDictionary<TSource, TKey>方法可 以將序列轉化爲字典。TSource表示source中的元素的類型;TKey表示keySelector返回的鍵的類型。其返回一個包含鍵和值的Dictionary<TKey, TValue>3725 
3726  
3727 
3728 var q =
3729 
3730   from p in db.Products
3731 
3732   where p.UnitsInStock <= p.ReorderLevel && ! p.Discontinued
3733 
3734   select p;
3735 
3736 Dictionary<int, Product> qDictionary=
3737 
3738   q.ToDictionary(p => p.ProductID);
3739 
3740 foreach (int key in qDictionary.Keys)
3741 
3742 {
3743 
3744    Console.WriteLine(key);
3745 
3746 }
3747 
3748  
3749 
3750 語句描述:這個例子使用 ToDictionary 將查詢和鍵表達式直接鍵表達式直接計算爲 Dictionary<K, T>3751 
3752  
3753 
3754 LINQ to SQL語句(19)之ADO.NET與LINQ to SQL
3755 ADO.NET與LINQ to SQL
3756 
3757  
3758 
3759 它基於由 ADO.NET 提供程序模型提供的服務。所以,咱們能夠將 LINQ to SQL 代碼與現有的 ADO.NET 應用程序混合在一塊兒,將當前 ADO.NET 解決方案遷移到 LINQ to SQL。
3760 
3761  
3762 
3763 1.鏈接
3764  
3765 
3766 在建立 LINQ to SQL DataContext 時,能夠提供現有 ADO.NET 鏈接。對DataContext 的全部操做(包括查詢)都使用所提供的這個鏈接。若是此鏈接已經打開,則在您使用完此鏈接時,LINQ to SQL 會保持它的打開狀態不變。咱們始終能夠訪問此鏈接,另外還可使用 Connection 屬性自行關閉它。
3767 
3768  
3769 
3770 //新建一個 標準的ADO.NET鏈接:
3771 
3772 SqlConnection nwindConn = new SqlConnection(connString);
3773 
3774 nwindConn.Open();
3775 
3776 // ... 其它的ADO.NET數據操做 代碼... //
3777 
3778 //利用現有的ADO.NET鏈接來建立一個DataContext:
3779 
3780 Northwind interop_db = new Northwind(nwindConn);
3781 
3782 var orders =
3783 
3784    from o in interop_db.Orders
3785 
3786    where o.Freight > 500.00M
3787 
3788    select o;
3789 
3790 //返回Freight>500.00M的訂單
3791 
3792 nwindConn.Close();
3793 
3794  
3795 
3796 語句描述:這個例子使用預先存在的ADO.NET 鏈接建立Northwind對象,本例中的查詢返回運費至少爲500.00 的全部訂單。
3797 
3798  
3799 
3800 2.事務
3801  
3802 
3803 當咱們已經啓動了本身的數據庫事務而且咱們但願 DataContext 包含在內時,咱們能夠向 DataContext 提供此事務。
3804 
3805  
3806 
3807 經過 .NET Framework 建立事務的首選方法是使用 TransactionScope 對象。經過使用此方法,咱們能夠建立跨數據庫及其餘駐留在內存中的資源管理器執行的分佈式事務。事務範圍幾乎不須要資源就能夠啓動。它們僅在事務範圍內存在多個鏈接時纔將自身提高爲分佈式事務。
3808 
3809  
3810 
3811 using (TransactionScope ts = newTransactionScope())
3812 
3813 {
3814 
3815   db.SubmitChanges();
3816 
3817   ts.Complete();
3818 
3819 }
3820 
3821  
3822 
3823 注意:不能將此方法用於全部數據庫。例如,SqlClient 鏈接在針對 SQL Server 2000 服務器使用時沒法提高系統事務。它採起的方法是,只要它發現有使用事務範圍的狀況,它就會自動向完整的分佈式事務登記。
3824 
3825  
3826 
3827 下面用一個例子說明一下事務的使用方法。在這裏,也說明了重用 ADO.NET 命令和 DataContext 之間的同一鏈接。
3828 
3829  
3830 
3831 var q =
3832 
3833    from p in db.Products
3834 
3835    where p.ProductID == 3
3836 
3837    select p;
3838 
3839 //使用LINQ to SQL查詢出來
3840 
3841 //新建一個標準的ADO.NET鏈接:
3842 
3843 SqlConnection nwindConn = newSqlConnection(connString);
3844 
3845 nwindConn.Open();
3846 
3847 //利用現有的 ADO.NET鏈接來建立一個DataContext:
3848 
3849 Northwind interop_db = newNorthwind(nwindConn);
3850 
3851 SqlTransaction nwindTxn =nwindConn.BeginTransaction();
3852 
3853 try
3854 
3855 {
3856 
3857   SqlCommand cmd = new SqlCommand("UPDATE Products SET"
3858 
3859    +"QuantityPerUnit = 'single item' WHERE ProductID = 3");
3860 
3861   cmd.Connection = nwindConn;
3862 
3863    cmd.Transaction = nwindTxn;
3864 
3865   cmd.ExecuteNonQuery();
3866 
3867    interop_db.Transaction = nwindTxn;
3868 
3869   Product prod1 = interop_db.Products.First(p => p.ProductID == 4);
3870 
3871   Product prod2 = interop_db.Products.First(p => p.ProductID == 5);
3872 
3873    prod1.UnitsInStock -= 3;
3874 
3875   prod2.UnitsInStock -= 5;//這有一個錯 誤,不能爲負數
3876 
3877   interop_db.SubmitChanges();
3878 
3879    nwindTxn.Commit();
3880 
3881 }
3882 
3883 catch (Exception e)
3884 
3885 {
3886 
3887   // 若是有一個錯誤,全部的操做回滾
3888 
3889   Console.WriteLine (e.Message);
3890 
3891 }
3892 
3893 nwindConn.Close();
3894 
3895  
3896 
3897 語句描述:這個例子使用預先存在的 ADO.NET 鏈接建立 Northwind 對象,而後與此對象共享一個 ADO.NET 事務。此事務既用於經過 ADO.NET 鏈接執行 SQL 命令,又用於經過 Northwind 對象提交更改。當事務因違反 CHECK 約束而停止時,將回滾全部更改,包括經過 SqlCommand 作出的更改,以及經過Northwind 對象作出的更改。
3898 
3899  
3900 
3901  
3902 
3903 LINQ to SQL語句(20)之存儲過程
3904 存儲過程
3905 
3906  
3907 
3908 在咱們編寫程序中,每每須要一些存儲過程,在LINQ to SQL中怎麼使用呢?也許比原來的更簡單些。下面咱們以NORTHWND.MDF數據庫中自帶的幾個存儲過程來理解一下。
3909 
3910  
3911 
3912 1.標量返回
3913  
3914 
3915 在數據庫中,有名爲 Customers Count By Region的存儲過程。該存儲過程返回顧客所在"WA"區域的數量。
3916 
3917  
3918 
3919 ALTER PROCEDURE [dbo]. [NonRowset]
3920 
3921   (@param1 NVARCHAR(15))
3922 
3923 AS
3924 
3925 BEGIN
3926 
3927   SET NOCOUNT ON;
3928 
3929    DECLARE @count int
3930 
3931    SELECT @count = COUNT(*)FROM Customers
3932 
3933    WHERECustomers.Region = @Param1
3934 
3935    RETURN @count
3936 
3937 END
3938 
3939  
3940 
3941 咱們只要把這個存儲過程拖到O/R設計器內,它自動生成了如下代碼段:
3942 
3943  
3944 
3945 [Function(Name = "dbo.[Customers CountBy Region]")]
3946 
3947 public intCustomers_Count_By_Region([Parameter
3948 
3949 (DbType = "NVarChar (15)")]string param1)
3950 
3951 {
3952 
3953   IExecuteResult result = this.ExecuteMethodCall(this,
3954 
3955   ((MethodInfo) (MethodInfo.GetCurrentMethod())), param1);
3956 
3957   return ((int) (result.ReturnValue));
3958 
3959 }
3960 
3961  
3962 
3963 咱們須要時,直接調用就能夠了,例如:
3964 
3965  
3966 
3967 int count = db.CustomersCountByRegion("WA");
3968 
3969 Console.WriteLine(count);
3970 
3971  
3972 
3973 語句描述:這個實例使用存儲過程返回在「WA」地區的客戶數。
3974 
3975  
3976 
3977 2.單一結果集
3978  
3979 
3980 從數據庫中返回行集合,幷包含用於篩選結果的輸入參數。當咱們執行 返回行集合的存儲過程時,會用到結果類,它存儲從存儲過程當中返回的結果。
3981 
3982  
3983 
3984 下面的示例表示一個存儲過程,該存儲過程返回客戶行並使用輸入參數來僅返回將「London」列爲客戶城市的那些行的固定幾列。 
3985 
3986  
3987 
3988 ALTER PROCEDURE [dbo].[Customers By City]
3989 
3990    -- Add the parameters for the stored procedure here
3991 
3992    (@param1 NVARCHAR(20))
3993 
3994 AS
3995 
3996 BEGIN
3997 
3998    -- SET NOCOUNT ON added to prevent extra result sets from
3999 
4000    -- interfering with SELECT statements.
4001 
4002    SET NOCOUNT ON;
4003 
4004    SELECT CustomerID, ContactName, CompanyName, City from
4005 
4006    Customers as c where c.City=@param1
4007 
4008 END
4009 
4010  
4011 
4012 拖到O/R設計器內,它自動生成了如下代碼段:
4013 
4014  
4015 
4016 [Function(Name="dbo.[Customers ByCity]")]
4017 
4018 publicISingleResult<Customers_By_CityResult> Customers_By_City(
4019 
4020 [Parameter(DbType="NVarChar(20)")]string param1)
4021 
4022 {
4023 
4024   IExecuteResult result = this.ExecuteMethodCall(this, (
4025 
4026   (MethodInfo) (MethodInfo.GetCurrentMethod())), param1);
4027 
4028   return ((ISingleResult<Customers_By_CityResult>)
4029 
4030    (result.ReturnValue));
4031 
4032 }
4033 
4034  
4035 
4036 咱們用下面的代碼調用:
4037 
4038  
4039 
4040 ISingleResult<Customers_By_CityResult>result =
4041 
4042 db.Customers_By_City("London");
4043 
4044 foreach (Customers_By_CityResult cust inresult)
4045 
4046 {
4047 
4048    Console.WriteLine("CustID={0}; City={1}",cust.CustomerID,
4049 
4050     cust.City);
4051 
4052 }
4053 
4054  
4055 
4056 語句描述:這個實例使用存儲過程返回在倫敦的客戶的 CustomerID和City。
4057 
4058  
4059 
4060 3.多個可能形狀的單一結果集
4061  
4062 
4063 當存儲過程能夠返回多個結果形狀時,返回類型沒法強類型化爲單個投影形狀。儘管 LINQ to SQL 能夠生成全部可能的投影類型,但它沒法獲知將以何種順序返回它們。 ResultTypeAttribute 屬性適用於返回多個結果類型的存儲過程,用以指定該過程能夠返回的類型的集合。
4064 
4065  
4066 
4067 在下面的 SQL 代碼示例中,結果形狀取決於輸入(param1 = 1或param1 = 2)。咱們不知道先返回哪一個投影。
4068 
4069  
4070 
4071 ALTER PROCEDURE [dbo].[SingleRowset_MultiShape]
4072 
4073    -- Add the parameters for the stored procedure here
4074 
4075    (@param1 int )
4076 
4077 AS
4078 
4079 BEGIN
4080 
4081    -- SET NOCOUNT ON added to prevent extra result sets from
4082 
4083    -- interfering with SELECT statements.
4084 
4085    SET NOCOUNT ON;
4086 
4087    if(@param1 = 1)
4088 
4089    SELECT * from Customers as c where c.Region = 'WA'
4090 
4091    else if (@param1 = 2)
4092 
4093    SELECT CustomerID, ContactName, CompanyName from
4094 
4095    Customers as c where c.Region = 'WA'
4096 
4097 END
4098 
4099  
4100 
4101 拖到O/R 設計器內,它自動生成了如下代碼段:
4102 
4103  
4104 
4105 [Function (Name="dbo.[Whole Or PartialCustomers Set]")]
4106 
4107 publicISingleResult<Whole_Or_Partial_Customers_SetResult>
4108 
4109 Whole_Or_Partial_Customers_Set([Parameter(DbType="Int")]
4110 
4111 System.Nullable<int> param1)
4112 
4113 {
4114 
4115    IExecuteResult result = this.ExecuteMethodCall(this,
4116 
4117    ((MethodInfo)(MethodInfo.GetCurrentMethod())), param1);
4118 
4119    return ((ISingleResult<Whole_Or_Partial_Customers_SetResult>)
4120 
4121   (result.ReturnValue));
4122 
4123 }
4124 
4125  
4126 
4127 可是,VS2008會把多結果集存儲過程識別爲單結果集的存儲過程,默認生成的代碼咱們要手動修改一下,要求返回多個結果集,像這樣:
4128 
4129  
4130 
4131 [Function(Name="dbo.[Whole Or PartialCustomers Set]")]
4132 
4133 [ResultType(typeof (WholeCustomersSetResult))]
4134 
4135 [ResultType(typeof(PartialCustomersSetResult))]
4136 
4137 public IMultipleResultsWhole_Or_Partial_Customers_Set([Parameter
4138 
4139 (DbType="Int")]System.Nullable<int> param1)
4140 
4141 {
4142 
4143   IExecuteResult result = this.ExecuteMethodCall(this,
4144 
4145    ((MethodInfo)(MethodInfo.GetCurrentMethod())), param1);
4146 
4147    return ((IMultipleResults)(result.ReturnValue));
4148 
4149 }
4150 
4151  
4152 
4153 咱們分別定義了兩個分部類,用於指定返回的類型。WholeCustomersSetResult類 如 下:
4154 
4155  
4156 
4157 public partial classWholeCustomersSetResult
4158 
4159 {
4160 
4161   private string _CustomerID;
4162 
4163   private string _CompanyName;
4164 
4165   private string _ContactName;
4166 
4167   private string _ContactTitle;
4168 
4169   private string _Address;
4170 
4171    private string _City;
4172 
4173   private string _Region;
4174 
4175    private string _PostalCode;
4176 
4177   private string _Country;
4178 
4179   private string _Phone;
4180 
4181   private string _Fax;
4182 
4183   public WholeCustomersSetResult()
4184 
4185   {
4186 
4187   }
4188 
4189   [Column (Storage = "_CustomerID", DbType ="NChar(5)")]
4190 
4191   public string CustomerID
4192 
4193   {
4194 
4195     get { return this._CustomerID; }
4196 
4197     set
4198 
4199     {
4200 
4201        if ((this._CustomerID != value))
4202 
4203         this._CustomerID = value;
4204 
4205     }
4206 
4207   }
4208 
4209   [Column(Storage = "_CompanyName", DbType ="NVarChar(40)")]
4210 
4211   public string CompanyName
4212 
4213   {
4214 
4215     get { return this._CompanyName; }
4216 
4217     set
4218 
4219     {
4220 
4221        if ((this._CompanyName != value))
4222 
4223          this._CompanyName = value;
4224 
4225     }
4226 
4227   }
4228 
4229   [Column (Storage = "_ContactName", DbType ="NVarChar(30) ")]
4230 
4231   public string ContactName
4232 
4233   {
4234 
4235      get { return this._ContactName; }
4236 
4237     set
4238 
4239     {
4240 
4241       if ((this._ContactName != value))
4242 
4243          this._ContactName = value;
4244 
4245     }
4246 
4247   }
4248 
4249   [Column (Storage = "_ContactTitle", DbType ="NVarChar(30) ")]
4250 
4251   public string ContactTitle
4252 
4253   {
4254 
4255      get { return this._ContactTitle; }
4256 
4257     set
4258 
4259     {
4260 
4261       if ((this._ContactTitle != value))
4262 
4263          this._ContactTitle = value;
4264 
4265     }
4266 
4267   }
4268 
4269    [Column(Storage = "_Address", DbType = "NVarChar(60)")]
4270 
4271   public string Address
4272 
4273   {
4274 
4275     get { return this._Address; }
4276 
4277     set
4278 
4279     {
4280 
4281       if ((this._Address != value))
4282 
4283         this._Address = value;
4284 
4285     }
4286 
4287   }
4288 
4289   [Column(Storage = "_City", DbType = "NVarChar(15)")]
4290 
4291   public string City
4292 
4293   {
4294 
4295     get { return this._City; }
4296 
4297     set
4298 
4299     {
4300 
4301       if ((this._City != value))
4302 
4303         this._City = value;
4304 
4305     }
4306 
4307   }
4308 
4309   [Column(Storage = "_Region", DbType = "NVarChar(15)")]
4310 
4311   public string Region
4312 
4313   {
4314 
4315     get { return this._Region; }
4316 
4317     set
4318 
4319     {
4320 
4321       if ((this._Region != value))
4322 
4323         this._Region = value;
4324 
4325     }
4326 
4327   }
4328 
4329   [Column(Storage = "_PostalCode", DbType ="NVarChar(10)")]
4330 
4331    public string PostalCode
4332 
4333   {
4334 
4335     get { return this._PostalCode; }
4336 
4337     set
4338 
4339     {
4340 
4341        if ((this._PostalCode != value))
4342 
4343         this._PostalCode = value;
4344 
4345     }
4346 
4347   }
4348 
4349   [Column(Storage = "_Country", DbType ="NVarChar(15)")]
4350 
4351    public string Country
4352 
4353   {
4354 
4355     get { return this._Country; }
4356 
4357     set
4358 
4359     {
4360 
4361       if ((this._Country != value))
4362 
4363         this._Country = value;
4364 
4365     }
4366 
4367   }
4368 
4369   [Column(Storage = "_Phone", DbType ="NVarChar(24)")]
4370 
4371    public string Phone
4372 
4373   {
4374 
4375     get { return this._Phone; }
4376 
4377     set
4378 
4379     {
4380 
4381       if ((this._Phone != value))
4382 
4383         this._Phone = value;
4384 
4385     }
4386 
4387   }
4388 
4389   [Column(Storage = "_Fax", DbType ="NVarChar(24)")]
4390 
4391   public string Fax
4392 
4393   {
4394 
4395     get { return this._Fax; }
4396 
4397     set
4398 
4399     {
4400 
4401       if ((this._Fax != value))
4402 
4403         this._Fax = value;
4404 
4405     }
4406 
4407   }
4408 
4409 }
4410 
4411  
4412 
4413 PartialCustomersSetResult類 以下:
4414 
4415  
4416 
4417 public partial classPartialCustomersSetResult
4418 
4419 {
4420 
4421   private string _CustomerID;
4422 
4423   private string _ContactName;
4424 
4425   private string _CompanyName;
4426 
4427   public PartialCustomersSetResult()
4428 
4429   {
4430 
4431   }
4432 
4433   [Column (Storage = "_CustomerID", DbType ="NChar(5)")]
4434 
4435   public string CustomerID
4436 
4437   {
4438 
4439     get { return this._CustomerID; }
4440 
4441     set
4442 
4443     {
4444 
4445        if ((this._CustomerID != value))
4446 
4447         this._CustomerID = value;
4448 
4449     }
4450 
4451   }
4452 
4453   [Column(Storage = "_ContactName", DbType ="NVarChar(30)")]
4454 
4455   public string ContactName
4456 
4457   {
4458 
4459     get { return this._ContactName; }
4460 
4461     set
4462 
4463     {
4464 
4465        if ((this._ContactName != value))
4466 
4467          this._ContactName = value;
4468 
4469     }
4470 
4471   }
4472 
4473   [Column (Storage = "_CompanyName", DbType ="NVarChar(40) ")]
4474 
4475   public string CompanyName
4476 
4477   {
4478 
4479      get { return this._CompanyName; }
4480 
4481     set
4482 
4483     {
4484 
4485       if ((this._CompanyName != value))
4486 
4487          this._CompanyName = value;
4488 
4489     }
4490 
4491   }
4492 
4493 }
4494 
4495  
4496 
4497 這樣就可使用了,下面代碼直接調用,分別返回各自的結果集合。
4498 
4499  
4500 
4501 //返回所有Customer結果集
4502 
4503 IMultipleResults result =db.Whole_Or_Partial_Customers_Set(1);
4504 
4505 IEnumerable<WholeCustomersSetResult>shape1 =
4506 
4507 result.GetResult<WholeCustomersSetResult>();
4508 
4509 foreach (WholeCustomersSetResult compNamein shape1)
4510 
4511 {
4512 
4513    Console.WriteLine(compName.CompanyName);
4514 
4515 }
4516 
4517 //返回部分 Customer結果集
4518 
4519 result =db.Whole_Or_Partial_Customers_Set(2);
4520 
4521 IEnumerable<PartialCustomersSetResult>shape2 =
4522 
4523 result.GetResult<PartialCustomersSetResult>();
4524 
4525 foreach (PartialCustomersSetResult con inshape2)
4526 
4527 {
4528 
4529    Console.WriteLine(con.ContactName);
4530 
4531 }
4532 
4533  
4534 
4535 語句描述:這個實例使用存儲過程返回「WA」地區中的一組客戶。返回的結果集形狀取決於傳入的參數。若是參數等於 1,則返回全部客戶屬性。若是參數等於2,則返回ContactName屬性。
4536 
4537  
4538 
4539 4.多個結果集
4540  
4541 
4542 這種存儲過程能夠生成多個結果形狀,但咱們已經知道結果的返回順序。
4543 
4544  
4545 
4546 下面是一個按順序返回多個結果集的存儲過程Get Customer And Orders。 返回顧客ID爲"SEVES"的顧客和他們全部的訂單。
4547 
4548  
4549 
4550 ALTER PROCEDURE [dbo].[Get Customer AndOrders]
4551 
4552 (@CustomerID nchar(5))
4553 
4554   -- Add the parameters for the stored procedure here
4555 
4556 AS
4557 
4558 BEGIN
4559 
4560    -- SET NOCOUNT ON added to prevent extra result sets from
4561 
4562   -- interfering with SELECT statements.
4563 
4564   SET NOCOUNT ON;
4565 
4566    SELECT * FROM Customers AS c WHERE c.CustomerID = @CustomerID 
4567 
4568   SELECT * FROM Orders AS o WHERE o.CustomerID = @CustomerID
4569 
4570 END
4571 
4572  
4573 
4574 拖到設計器代碼以下:
4575 
4576  
4577 
4578 [Function (Name="dbo.[Get Customer AndOrders]")]
4579 
4580 publicISingleResult<Get_Customer_And_OrdersResult>
4581 
4582 Get_Customer_And_Orders([Parameter(Name="CustomerID",
4583 
4584 DbType="NChar(5)")] stringcustomerID)
4585 
4586 {
4587 
4588    IExecuteResult result = this.ExecuteMethodCall(this,
4589 
4590    ((MethodInfo)(MethodInfo.GetCurrentMethod())), customerID);
4591 
4592    return ((ISingleResult<Get_Customer_And_OrdersResult>)
4593 
4594    (result.ReturnValue));
4595 
4596 }
4597 
4598  
4599 
4600 一樣,咱們要修改自動生成的代碼:
4601 
4602  
4603 
4604 [Function(Name="dbo.[Get Customer AndOrders] ")]
4605 
4606 [ResultType(typeof(CustomerResultSet))]
4607 
4608 [ResultType(typeof(OrdersResultSet))]
4609 
4610 public IMultipleResultsGet_Customer_And_Orders
4611 
4612 ([Parameter(Name="CustomerID",DbType="NChar(5)")]
4613 
4614 string customerID)
4615 
4616 {
4617 
4618   IExecuteResult result = this.ExecuteMethodCall(this,
4619 
4620   ((MethodInfo) (MethodInfo.GetCurrentMethod())), customerID);
4621 
4622   return ((IMultipleResults)(result.ReturnValue));
4623 
4624 }
4625 
4626  
4627 
4628 一樣,本身手寫類,讓其存儲過程返回各自的結果集。
4629 
4630  
4631 
4632 CustomerResultSet類
4633 
4634  
4635 
4636 public partial class CustomerResultSet
4637 
4638 {
4639 
4640   private string _CustomerID;
4641 
4642   private string _CompanyName;
4643 
4644   private string _ContactName;
4645 
4646   private string _ContactTitle;
4647 
4648   private string _Address;
4649 
4650    private string _City;
4651 
4652   private string _Region;
4653 
4654    private string _PostalCode;
4655 
4656   private string _Country;
4657 
4658   private string _Phone;
4659 
4660   private string _Fax;
4661 
4662   public CustomerResultSet()
4663 
4664   {
4665 
4666   }
4667 
4668   [Column(Storage = "_CustomerID", DbType ="NChar(5)")]
4669 
4670    public string CustomerID
4671 
4672   {
4673 
4674     get { return this._CustomerID; }
4675 
4676     set
4677 
4678     {
4679 
4680        if ((this._CustomerID != value))
4681 
4682         this._CustomerID = value;
4683 
4684     }
4685 
4686   }
4687 
4688   [Column(Storage = "_CompanyName", DbType ="NVarChar(40)")]
4689 
4690   public string CompanyName
4691 
4692   {
4693 
4694     get { return this._CompanyName; }
4695 
4696     set
4697 
4698     {
4699 
4700        if ((this._CompanyName != value))
4701 
4702          this._CompanyName = value;
4703 
4704     }
4705 
4706   }
4707 
4708   [Column (Storage = "_ContactName", DbType ="NVarChar(30) ")]
4709 
4710   public string ContactName
4711 
4712   {
4713 
4714      get { return this._ContactName; }
4715 
4716     set
4717 
4718     {
4719 
4720       if ((this._ContactName != value))
4721 
4722          this._ContactName = value;
4723 
4724     }
4725 
4726   }
4727 
4728   [Column (Storage = "_ContactTitle", DbType ="NVarChar(30) ")]
4729 
4730   public string ContactTitle
4731 
4732   {
4733 
4734      get { return this._ContactTitle; }
4735 
4736     set
4737 
4738     {
4739 
4740       if ((this._ContactTitle != value))
4741 
4742          this._ContactTitle = value;
4743 
4744     }
4745 
4746   }
4747 
4748    [Column(Storage = "_Address", DbType = "NVarChar(60)")]
4749 
4750   public string Address
4751 
4752   {
4753 
4754     get { return this._Address; }
4755 
4756     set
4757 
4758     {
4759 
4760       if ((this._Address != value))
4761 
4762         this._Address = value;
4763 
4764     }
4765 
4766   }
4767 
4768   [Column(Storage = "_City", DbType ="NVarChar(15)")]
4769 
4770   public string City
4771 
4772   {
4773 
4774     get { return this._City; }
4775 
4776     set
4777 
4778     {
4779 
4780       if ((this._City != value))
4781 
4782         this._City = value;
4783 
4784     }
4785 
4786   }
4787 
4788   [Column(Storage = "_Region", DbType = "NVarChar(15)")]
4789 
4790   public string Region
4791 
4792   {
4793 
4794     get { return this._Region; }
4795 
4796     set
4797 
4798     {
4799 
4800       if ((this._Region != value))
4801 
4802         this._Region = value;
4803 
4804     }
4805 
4806   }
4807 
4808   [Column(Storage = "_PostalCode", DbType ="NVarChar(10)")]
4809 
4810    public string PostalCode
4811 
4812   {
4813 
4814     get { return this._PostalCode; }
4815 
4816     set
4817 
4818     {
4819 
4820        if ((this._PostalCode != value))
4821 
4822         this._PostalCode = value;
4823 
4824     }
4825 
4826   }
4827 
4828   [Column(Storage = "_Country", DbType ="NVarChar(15)")]
4829 
4830    public string Country
4831 
4832   {
4833 
4834     get { return this._Country; }
4835 
4836     set
4837 
4838     {
4839 
4840       if ((this._Country != value))
4841 
4842         this._Country = value;
4843 
4844     }
4845 
4846   }
4847 
4848   [Column(Storage = "_Phone", DbType ="NVarChar(24)")]
4849 
4850    public string Phone
4851 
4852   {
4853 
4854     get { return this._Phone; }
4855 
4856     set
4857 
4858     {
4859 
4860       if ((this._Phone != value))
4861 
4862         this._Phone = value;
4863 
4864     }
4865 
4866   }
4867 
4868   [Column(Storage = "_Fax", DbType ="NVarChar(24)")]
4869 
4870   public string Fax
4871 
4872   {
4873 
4874     get { return this._Fax; }
4875 
4876     set
4877 
4878     {
4879 
4880       if ((this._Fax != value))
4881 
4882         this._Fax = value;
4883 
4884     }
4885 
4886   }
4887 
4888 }
4889 
4890  
4891 
4892 OrdersResultSet 類
4893 
4894  
4895 
4896 public partial class OrdersResultSet
4897 
4898 {
4899 
4900   private System.Nullable<int> _OrderID;
4901 
4902   private string _CustomerID;
4903 
4904   private System.Nullable<int> _EmployeeID;
4905 
4906   private System.Nullable<System.DateTime> _OrderDate;
4907 
4908   private System.Nullable<System.DateTime> _RequiredDate;
4909 
4910   private System.Nullable<System.DateTime> _ShippedDate;
4911 
4912   private System.Nullable<int> _ShipVia;
4913 
4914   private System.Nullable<decimal> _Freight;
4915 
4916    private string _ShipName;
4917 
4918   private string _ShipAddress;
4919 
4920   private string _ShipCity;
4921 
4922   private string _ShipRegion;
4923 
4924   private string _ShipPostalCode;
4925 
4926   private string _ShipCountry;
4927 
4928   public OrdersResultSet()
4929 
4930   {
4931 
4932   }
4933 
4934   [Column(Storage = "_OrderID", DbType = "Int")]
4935 
4936   public System.Nullable<int> OrderID
4937 
4938   {
4939 
4940     get { return this._OrderID; }
4941 
4942     set
4943 
4944     {
4945 
4946       if ((this._OrderID != value))
4947 
4948         this._OrderID = value;
4949 
4950     }
4951 
4952   }
4953 
4954   [Column(Storage = "_CustomerID", DbType ="NChar(5)")]
4955 
4956   public string CustomerID
4957 
4958   {
4959 
4960     get { return this._CustomerID; }
4961 
4962     set
4963 
4964     {
4965 
4966       if ((this._CustomerID != value))
4967 
4968         this._CustomerID = value;
4969 
4970     }
4971 
4972   }
4973 
4974    [Column(Storage = "_EmployeeID", DbType ="Int")]
4975 
4976   public System.Nullable<int> EmployeeID
4977 
4978   {
4979 
4980     get { return this._EmployeeID; }
4981 
4982     set
4983 
4984     {
4985 
4986       if ((this._EmployeeID != value))
4987 
4988         this._EmployeeID = value;
4989 
4990     }
4991 
4992   }
4993 
4994    [Column(Storage = "_OrderDate", DbType ="DateTime")]
4995 
4996   public System.Nullable<System.DateTime> OrderDate
4997 
4998   {
4999 
5000     get { return this._OrderDate; }
5001 
5002     set
5003 
5004     {
5005 
5006       if ((this._OrderDate != value))
5007 
5008          this._OrderDate = value;
5009 
5010     }
5011 
5012   }
5013 
5014   [Column (Storage = "_RequiredDate", DbType ="DateTime")]
5015 
5016   public System.Nullable<System.DateTime> RequiredDate
5017 
5018   {
5019 
5020     get { return this._RequiredDate; }
5021 
5022     set
5023 
5024     {
5025 
5026       if ((this._RequiredDate != value))
5027 
5028          this._RequiredDate = value;
5029 
5030     }
5031 
5032   }
5033 
5034    [Column(Storage = "_ShippedDate", DbType ="DateTime")]
5035 
5036   public System.Nullable<System.DateTime> ShippedDate
5037 
5038   {
5039 
5040     get { return this._ShippedDate; }
5041 
5042     set
5043 
5044      {
5045 
5046       if ((this._ShippedDate != value))
5047 
5048         this._ShippedDate = value;
5049 
5050     }
5051 
5052   }
5053 
5054    [Column(Storage = "_ShipVia", DbType = "Int")]
5055 
5056   public System.Nullable<int> ShipVia
5057 
5058   {
5059 
5060     get { return this._ShipVia; }
5061 
5062     set
5063 
5064     {
5065 
5066       if ((this._ShipVia != value))
5067 
5068          this._ShipVia = value;
5069 
5070     }
5071 
5072   }
5073 
5074   [Column (Storage = "_Freight", DbType ="Money")]
5075 
5076   public System.Nullable<decimal> Freight
5077 
5078   {
5079 
5080     get { return this._Freight; }
5081 
5082     set
5083 
5084     {
5085 
5086       if ((this._Freight != value))
5087 
5088          this._Freight = value;
5089 
5090     }
5091 
5092   }
5093 
5094   [Column (Storage = "_ShipName", DbType ="NVarChar(40)")]
5095 
5096   public string ShipName
5097 
5098   {
5099 
5100     get { return this._ShipName; }
5101 
5102     set
5103 
5104     {
5105 
5106       if ((this._ShipName != value))
5107 
5108         this._ShipName = value;
5109 
5110     }
5111 
5112   }
5113 
5114   [Column(Storage = "_ShipAddress", DbType ="NVarChar(60)")]
5115 
5116   public string ShipAddress
5117 
5118   {
5119 
5120     get { return this._ShipAddress; }
5121 
5122     set
5123 
5124     {
5125 
5126        if ((this._ShipAddress != value))
5127 
5128          this._ShipAddress = value;
5129 
5130     }
5131 
5132   }
5133 
5134   [Column (Storage = "_ShipCity", DbType ="NVarChar(15)")]
5135 
5136   public string ShipCity
5137 
5138   {
5139 
5140     get { return this._ShipCity; }
5141 
5142     set
5143 
5144     {
5145 
5146       if ((this._ShipCity != value))
5147 
5148         this._ShipCity = value;
5149 
5150     }
5151 
5152   }
5153 
5154   [Column(Storage = "_ShipRegion", DbType ="NVarChar(15)")]
5155 
5156    public string ShipRegion
5157 
5158   {
5159 
5160     get { return this._ShipRegion; }
5161 
5162     set
5163 
5164     {
5165 
5166        if ((this._ShipRegion != value))
5167 
5168         this._ShipRegion = value;
5169 
5170     }
5171 
5172   }
5173 
5174   [Column(Storage = "_ShipPostalCode", DbType ="NVarChar(10)")]
5175 
5176   public string ShipPostalCode
5177 
5178   {
5179 
5180     get { return this._ShipPostalCode; }
5181 
5182     set
5183 
5184     {
5185 
5186       if ((this._ShipPostalCode != value))
5187 
5188          this._ShipPostalCode = value;
5189 
5190     }
5191 
5192   }
5193 
5194    [Column(Storage = "_ShipCountry", DbType = "NVarChar(15)")]
5195 
5196   public string ShipCountry
5197 
5198   {
5199 
5200     get { return this._ShipCountry; }
5201 
5202     set
5203 
5204     {
5205 
5206       if ((this._ShipCountry != value))
5207 
5208          this._ShipCountry = value;
5209 
5210     }
5211 
5212   }
5213 
5214 }
5215 
5216  
5217 
5218  
5219 
5220 這時,只要調用就能夠了。
5221 
5222  
5223 
5224 IMultipleResults result =db.Get_Customer_And_Orders("SEVES");
5225 
5226 //返回 Customer結果集
5227 
5228 IEnumerable<CustomerResultSet>customer =
5229 
5230 result.GetResult<CustomerResultSet>();
5231 
5232 //返回Orders結果集
5233 
5234 IEnumerable<OrdersResultSet> orders =
5235 
5236 result.GetResult<OrdersResultSet>();
5237 
5238 //在這裏,咱們讀取CustomerResultSet中的數據
5239 
5240 foreach (CustomerResultSet cust incustomer)
5241 
5242 {
5243 
5244   Console.WriteLine(cust.CustomerID);
5245 
5246 }
5247 
5248  
5249 
5250 語句描述:這個實例使用存儲過程返回客戶「SEVES」及其全部訂單。
5251 
5252  
5253 
5254 5.帶輸出參數
5255  
5256 
5257 LINQ to SQL 將輸出參數映射到引用參數 ,而且對於值類型,它將參數聲明爲能夠爲null。
5258 
5259  
5260 
5261 下面的示例帶有單個輸入參數(客戶 ID)並返回一個輸出參數(該客戶的總銷售額)。
5262 
5263  
5264 
5265 ALTER PROCEDURE [dbo].[CustOrderTotal]
5266 
5267 @CustomerID nchar(5),
5268 
5269 @TotalSales money OUTPUT
5270 
5271 AS
5272 
5273 SELECT @TotalSales =SUM(OD.UNITPRICE*(1-OD.DISCOUNT) * OD.QUANTITY)
5274 
5275 FROM ORDERS O, "ORDER DETAILS" OD
5276 
5277 where O.CUSTOMERID = @CustomerID AND O.ORDERID= OD.ORDERID
5278 
5279  
5280 
5281 把這個存儲過程拖到設計器中,圖片以下:
5282 
5283  
5284 
5285  
5286 
5287 其生成代碼以下:
5288 
5289  
5290 
5291 [Function(Name="dbo.CustOrderTotal")]
5292 
5293 public int CustOrderTotal (
5294 
5295 [Parameter(Name="CustomerID",DbType="NChar(5) ")]string customerID,
5296 
5297 [Parameter (Name="TotalSales",DbType="Money")]
5298 
5299  ref System.Nullable<decimal> totalSales)
5300 
5301 {
5302 
5303    IExecuteResult result = this.ExecuteMethodCall(this,
5304 
5305    ((MethodInfo)(MethodInfo.GetCurrentMethod())),
5306 
5307   customerID, totalSales);
5308 
5309   totalSales = ((System.Nullable<decimal>)
5310 
5311   (result.GetParameterValue(1)));
5312 
5313   return ((int) (result.ReturnValue));
5314 
5315 }
5316 
5317  
5318 
5319 咱們使用下面的語句調用此存儲過程:注意:輸出參數是按引用傳遞的,以支持參數爲「in/out」的方案。在這種狀況下,參數僅爲「out」。
5320 
5321  
5322 
5323 decimal? totalSales = 0;
5324 
5325 string customerID = "ALFKI";
5326 
5327 db.CustOrderTotal(customerID, reftotalSales);
5328 
5329 Console.WriteLine("Total Sales forCustomer '{0}' = {1:C}",
5330 
5331 customerID, totalSales);
5332 
5333  
5334 
5335 語句描述:這個實例使用返回 Out 參數的存儲過程。
5336 
5337  
5338 
5339 好了,就說到這裏了,其增刪改操做同理。相信你們經過這5個實例理解了存儲過程。
5340 
5341  
5342 
5343 LINQ to SQL語句(21)之用戶定義函數
5344 用戶定義函數
5345 
5346  
5347 
5348 咱們能夠在LINQ to SQL中使用用戶定義函數。只要把用戶定義函數拖到O/R設計器中,LINQ to SQL自動使用FunctionAttribute屬性和ParameterAttribute屬性(若是須要)將其函數指定爲方法。這時,咱們只需簡單調用便可。
5349 
5350  
5351 
5352 在這裏注意:使用用戶定義函數的時候必須知足如下形式之一,不然會出現InvalidOperationException異常狀況。
5353 
5354  
5355 
5356 具備正確映射屬性的方法調用的函數。這裏使用FunctionAttribute屬性和 ParameterAttribute屬性。
5357 
5358  
5359 
5360 特定於LINQ to SQL的靜態SQL方法。
5361 
5362  
5363 
5364 .NET Framework方法支持的函數。
5365 
5366  
5367 
5368 下面介紹幾個例子:
5369 
5370  
5371 
5372 1.在Select中使用用戶定義的標量函數
5373  
5374 
5375 所謂標量函數是指返回在 RETURNS 子句中定義的類型的單個數據值。可使用全部標量數據類型,包括 bigint 和 sql_variant。不支持 timestamp 數據類型、用戶定義數據類型和非標量類型(如 table 或 cursor)。在 BEGIN...END 塊中定義的函數主體包含返回該值的 Transact-SQL 語句系列。返回類型能夠是除 text、ntext、image 、cursor 和 timestamp 以外的任何數據類型。咱們在系統自帶的 NORTHWND.MDF數據庫中,有3個自定義函數,這裏使用  TotalProductUnitPriceByCategory,其代碼以下:
5376 
5377  
5378 
5379 ALTER FUNCTION[dbo].[TotalProductUnitPriceByCategory]
5380 
5381 (@categoryID int)
5382 
5383 RETURNS Money
5384 
5385 AS
5386 
5387 BEGIN
5388 
5389   -- Declare the return variable here
5390 
5391   DECLARE @ResultVar Money
5392 
5393   -- Add the T-SQL statements to compute the return value here
5394 
5395   SELECT @ResultVar = (Select SUM(UnitPrice)
5396 
5397             from Products
5398 
5399             where CategoryID = @categoryID)
5400 
5401   -- Return the result of the function
5402 
5403   RETURN @ResultVar
5404 
5405 END
5406 
5407  
5408 
5409 咱們將其拖到設計器中,LINQ to SQL經過使用 FunctionAttribute 屬性將類中定義的客戶端方法映射到用戶定義的函數。請注意,這個方法體會構造一個捕獲方法調用意向的表達式,並將該表達式傳遞給 DataContext 進行轉換和執行。
5410 
5411  
5412 
5413 [Function(Name="dbo.TotalProductUnitPriceByCategory",
5414 
5415 IsComposable=true)]
5416 
5417 public System.Nullable<decimal>TotalProductUnitPriceByCategory(
5418 
5419 [Parameter (DbType="Int")]System.Nullable<int> categoryID)
5420 
5421 {
5422 
5423   return ((System.Nullable<decimal>)(this.ExecuteMethodCall(this,
5424 
5425   ((MethodInfo) (MethodInfo.GetCurrentMethod())), categoryID)
5426 
5427    .ReturnValue));
5428 
5429 }
5430 
5431  
5432 
5433 咱們使用時,能夠用如下代碼來調用:
5434 
5435  
5436 
5437 var q = from c in db.Categories
5438 
5439     select new
5440 
5441     {
5442 
5443       c.CategoryID,
5444 
5445        TotalUnitPrice =
5446 
5447          db.TotalProductUnitPriceByCategory(c.CategoryID)
5448 
5449     };
5450 
5451  
5452 
5453 這時,LINQ to SQL自動生成SQL語句以下:
5454 
5455  
5456 
5457 SELECT [t0].[CategoryID],CONVERT(Decimal(29,4),
5458 
5459 [dbo].[TotalProductUnitPriceByCategory]([t0].[CategoryID]))
5460 
5461 AS [TotalUnitPrice] FROM [dbo].[Categories]AS [t0]
5462 
5463 2.在Where從句中 使用用戶定義的標量函數
5464 這個例子使用方法同上一個例子原理基本相同了,MinUnitPriceByCategory自定義函數以下:
5465 
5466  
5467 
5468 ALTER FUNCTION[dbo].[MinUnitPriceByCategory]
5469 
5470 (@categoryID INT
5471 
5472 )
5473 
5474 RETURNS Money
5475 
5476 AS
5477 
5478 BEGIN
5479 
5480   -- Declare the return variable here
5481 
5482   DECLARE @ResultVar Money
5483 
5484   -- Add the T -SQL statements to compute the return value here
5485 
5486   SELECT @ResultVar = MIN(p.UnitPrice) FROM Products as p
5487 
5488   WHERE p.CategoryID = @categoryID
5489 
5490   -- Return the result of the function
5491 
5492   RETURN @ResultVar
5493 
5494 END
5495 
5496  
5497 
5498 拖到設計器中,生成代碼以下:
5499 
5500  
5501 
5502 [Function (Name="dbo.MinUnitPriceByCategory",IsComposable=true)]
5503 
5504 public System.Nullable<decimal>MinUnitPriceByCategory(
5505 
5506 [Parameter(DbType="Int")]System.Nullable<int> categoryID)
5507 
5508 {
5509 
5510   return ((System.Nullable<decimal>) (this.ExecuteMethodCall(
5511 
5512   this, ((MethodInfo) (MethodInfo.GetCurrentMethod())),
5513 
5514    categoryID).ReturnValue));
5515 
5516 }
5517 
5518  
5519 
5520 這時可使用了:注意這裏在 LINQ to SQL 查詢中,對生成的用戶定義函數方法 MinUnitPriceByCategory的內聯調用。此函數不會當即執行,這是由於查詢會延 遲執行。延遲執行的查詢中包含的函數直到此查詢執行時纔會執行。爲此查詢生成的 SQL 會轉換成對數據庫中用戶定義函數的調用(請參見此查詢後面的生成的 SQL語句),當在查詢外部調用這個函數時,LINQ to SQL 會用方法調用表達式建立一個簡單查詢並執行。 
5521 
5522  
5523 
5524 var q =
5525 
5526   from p in db.Products
5527 
5528   where p.UnitPrice ==
5529 
5530    db.MinUnitPriceByCategory(p.CategoryID)
5531 
5532   select p;
5533 
5534  
5535 
5536 它自動生成的SQL語句以下:
5537 
5538  
5539 
5540 SELECT [t0]. [ProductID],[t0].[ProductName], [t0].[SupplierID],
5541 
5542 [t0]. [CategoryID],[t0].[QuantityPerUnit],[t0].[UnitPrice],
5543 
5544 [t0]. [UnitsInStock],[t0].[UnitsOnOrder],[t0].[ReorderLevel],
5545 
5546 [t0]. [Discontinued]FROM [dbo].[Products]AS [t0]
5547 
5548 WHERE [t0]. [UnitPrice] =
5549 
5550 [dbo].[MinUnitPriceByCategory]([t0].[CategoryID])
5551 
5552  
5553 
5554 3.使用用戶定義的表值函數
5555  
5556 
5557 表值函數返回單個行集(與存儲過程不一樣,存儲過程可返回多個結果形狀)。因爲表值函數的返回類型爲 Table,所以在 SQL 中可使用表的任何地方都可以使用表值函數。此外,您還能夠徹底像處理表那樣來處理表值函數。
5558 
5559  
5560 
5561 下面的 SQL 用戶定義函數顯式聲明其返回一個 TABLE。所以,隱式定義了所返回的行集結構。
5562 
5563 ALTER FUNCTION[dbo].[ProductsUnderThisUnitPrice]
5564 
5565 (@price Money
5566 
5567 )
5568 
5569 RETURNS TABLE
5570 
5571 AS
5572 
5573 RETURN
5574 
5575   SELECT *
5576 
5577    FROM Products as P
5578 
5579   Where p.UnitPrice < @price
5580 
5581  
5582 
5583 拖到設計器中,LINQ to SQL 按以下方式映射此函數:
5584 
5585  
5586 
5587 [Function(Name="dbo.ProductsUnderThisUnitPrice",
5588 
5589 IsComposable=true)]
5590 
5591 publicIQueryable<ProductsUnderThisUnitPriceResult>
5592 
5593 ProductsUnderThisUnitPrice([Parameter(DbType="Money")]
5594 
5595 System.Nullable<decimal> price)
5596 
5597 {
5598 
5599   return this.CreateMethodCallQuery
5600 
5601    <ProductsUnderThisUnitPriceResult>(this,
5602 
5603   ((MethodInfo) (MethodInfo.GetCurrentMethod())), price);
5604 
5605 }
5606 
5607  
5608 
5609 這時咱們小小的修改一下Discontinued屬性爲可空的bool類型。
5610 
5611  
5612 
5613 private System.Nullable<bool>_Discontinued;
5614 
5615 public System.Nullable<bool>Discontinued
5616 
5617 {
5618 
5619 }
5620 
5621  
5622 
5623 咱們能夠這樣調用使用了:
5624 
5625  
5626 
5627 var q = from p indb.ProductsUnderThisUnitPrice(10.25M)
5628 
5629     where ! (p.Discontinued ?? false)
5630 
5631     select p;
5632 
5633  
5634 
5635 其生成 SQL語句以下:
5636 
5637  
5638 
5639 SELECT [t0].[ProductID],[t0].[ProductName], [t0].[SupplierID],
5640 
5641 [t0].[CategoryID], [t0].[QuantityPerUnit],[t0].[UnitPrice],
5642 
5643 [t0].[UnitsInStock], [t0].[UnitsOnOrder],[t0].[ReorderLevel],
5644 
5645 [t0].[Discontinued]
5646 
5647 FROM [dbo].[ProductsUnderThisUnitPrice](@p0) AS [t0]
5648 
5649 WHERE NOT ((COALESCE([t0].[Discontinued],@p1)) = 1)
5650 
5651 -- @p0: Input Money (Size = 0; Prec = 19;Scale = 4) [10.25]
5652 
5653 -- @p1: Input Int (Size = 0; Prec = 0;Scale = 0) [0]
5654 
5655 4.以聯接方式使用用戶定義的表值函數
5656  
5657 
5658 咱們利用上面的ProductsUnderThisUnitPrice用戶定義函數,在 LINQ to SQL 中, 調用以下:
5659 
5660  
5661 
5662 var q =
5663 
5664   from c in db.Categories
5665 
5666   join p in db.ProductsUnderThisUnitPrice(8.50M) on
5667 
5668    c.CategoryID equals p.CategoryID into prods
5669 
5670   from p in prods
5671 
5672   select new
5673 
5674   {
5675 
5676     c.CategoryID,
5677 
5678     c.CategoryName,
5679 
5680     p.ProductName,
5681 
5682      p.UnitPrice
5683 
5684   };
5685 
5686  
5687 
5688 其生成的 SQL 代碼說明對此函數返回的表執行聯接。
5689 
5690  
5691 
5692 SELECT [t0].[CategoryID], [t0]. [CategoryName],
5693 
5694 [t1].[ProductName], [t1].[UnitPrice]
5695 
5696 FROM [dbo].[Categories] AS [t0]
5697 
5698 CROSS JOIN [dbo].[ProductsUnderThisUnitPrice](@p0) AS [t1]
5699 
5700 WHERE ([t0]. [CategoryID]) =[t1].[CategoryID]
5701 
5702 -- @p0: Input Money (Size = 0; Prec = 19;Scale = 4) [8.50]
5703 
5704  
5705 
5706  
5707 
5708 LINQ to SQL語句(22)之DataContext
5709 DataContext
5710 
5711  
5712 
5713 DataContext做爲LINQ to SQL框架的主入口點,爲咱們 提供了一些方法和屬性,本文用幾個例子說明DataContext幾個典型的應用。
5714 
5715  
5716 
5717 建立和刪除數據庫
5718  
5719 
5720 CreateDatabase方法用於在服務器上建立數據庫。
5721 
5722  
5723 
5724 DeleteDatabase方法用於刪除由DataContext鏈接字符串標識的數據 庫。
5725 
5726  
5727 
5728 數據庫的名稱有如下方法來定義:
5729 
5730  
5731 
5732 若是數據庫在鏈接字符串中標識,則使用該鏈接字符串的名稱。
5733 
5734  
5735 
5736 若是存在DatabaseAttribute屬性 (Attribute),則將其Name屬性(Property)用做數據庫的名稱。
5737 
5738  
5739 
5740 若是鏈接字符串中沒有數據庫標記,而且使用強類型的DataContext,則會檢查與 DataContext繼承類名稱相同的數據庫。若是使用弱類型的DataContext,則會引起異常。
5741 
5742  
5743 
5744 若是已經過使用文件名建立了DataContext,則會建立與該文件名相對應的數據庫。
5745 
5746  
5747 
5748 咱們首先用實體類描述關係數據庫表和列的結構的屬性。再調用DataContext的CreateDatabase方法,LINQ to SQL會用咱們的定義的實體類結構來構造一個新的數據庫實例。還能夠經過使用 .mdf 文件或只使用目錄名(取決於鏈接字符串),將 CreateDatabase與SQL Server一塊兒使用。 LINQ to SQL使用鏈接字符串來定義要建立的數據庫和做爲數據庫建立位置的服務器。
5749 
5750  
5751 
5752 說了這麼多,用一段實例說明一下吧!
5753 
5754  
5755 
5756 首先,咱們新建一個NewCreateDB類用於建立一個名爲NewCreateDB.mdf的新數據庫,該數據庫有一個Person表,有三個字段,分別爲PersonID、PersonName、Age。
5757 
5758  
5759 
5760 public class NewCreateDB : DataContext
5761 
5762 {
5763 
5764   public Table<Person> Persons;
5765 
5766   public NewCreateDB (string connection)
5767 
5768     :
5769 
5770     base(connection)
5771 
5772   {
5773 
5774   }
5775 
5776   public NewCreateDB(System.Data.IDbConnection connection)
5777 
5778     :
5779 
5780     base(connection)
5781 
5782   {
5783 
5784   }
5785 
5786 }
5787 
5788 [Table(Name = "Person")]
5789 
5790 public partial class Person :INotifyPropertyChanged
5791 
5792 {
5793 
5794   private int _PersonID;
5795 
5796   private string _PersonName;
5797 
5798   private System.Nullable<int> _Age;
5799 
5800   public Person() { }
5801 
5802   [Column(Storage = "_PersonID", DbType = "INT",
5803 
5804     IsPrimaryKey = true)]
5805 
5806   public int PersonID
5807 
5808   {
5809 
5810     get { return this._PersonID; }
5811 
5812     set
5813 
5814     {
5815 
5816       if ((this._PersonID != value))
5817 
5818       {
5819 
5820          this.OnPropertyChanged("PersonID");
5821 
5822          this._PersonID = value;
5823 
5824         this.OnPropertyChanged ("PersonID");
5825 
5826       }
5827 
5828     }
5829 
5830   }
5831 
5832   [Column(Storage = "_PersonName", DbType ="NVarChar(30)")]
5833 
5834   public string PersonName
5835 
5836    {
5837 
5838     get { return this._PersonName; }
5839 
5840     set
5841 
5842     {
5843 
5844       if ((this._PersonName != value))
5845 
5846       {
5847 
5848         this.OnPropertyChanged ("PersonName");
5849 
5850         this._PersonName = value;
5851 
5852         this.OnPropertyChanged ("PersonName");
5853 
5854       }
5855 
5856     }
5857 
5858   }
5859 
5860   [Column(Storage = "_Age", DbType = "INT")]
5861 
5862   public System.Nullable<int> Age
5863 
5864   {
5865 
5866     get { return this._Age; }
5867 
5868     set
5869 
5870     {
5871 
5872       if ((this._Age != value))
5873 
5874        {
5875 
5876         this.OnPropertyChanged("Age");
5877 
5878         this._Age = value;
5879 
5880          this.OnPropertyChanged("Age");
5881 
5882       }
5883 
5884     }
5885 
5886   }
5887 
5888   public event PropertyChangedEventHandler PropertyChanged;
5889 
5890   protected virtual void OnPropertyChanged (string PropertyName)
5891 
5892   {
5893 
5894     if ((this.PropertyChanged != null))
5895 
5896     {
5897 
5898        this.PropertyChanged(this,
5899 
5900         new PropertyChangedEventArgs(PropertyName));
5901 
5902     }
5903 
5904   }
5905 
5906 }
5907 
5908  
5909 
5910 接下來的一段代碼先建立一個數據庫,在調用 CreateDatabase後,新的數據庫就會存在而且會接受通常的查詢和命令。接着插入一條記錄而且查詢。最後刪除這個數據庫。
5911 
5912  
5913 
5914 //1.新建一個臨時 文件夾來存放新建的數據庫
5915 
5916 string userTempFolder =Environment.GetEnvironmentVariable
5917 
5918 ("SystemDrive") +@"YJingLee";
5919 
5920 Directory.CreateDirectory (userTempFolder);
5921 
5922 //2.新建數據庫NewCreateDB
5923 
5924 string userMDF = System.IO.Path.Combine(userTempFolder,
5925 
5926   @"NewCreateDB.mdf");
5927 
5928 string connStr = String.Format (@"DataSource=.SQLEXPRESS;
5929 
5930 AttachDbFilename={0};IntegratedSecurity=True;
5931 
5932 Connect Timeout=30;User Instance=True;
5933 
5934 Integrated Security = SSPI;",userMDF);
5935 
5936 NewCreateDB newDB = newNewCreateDB(connStr);
5937 
5938 newDB.CreateDatabase();
5939 
5940 //3.插入 數據並查詢
5941 
5942 var newRow = new Person
5943 
5944 {
5945 
5946    PersonID = 1,
5947 
5948    PersonName = "YJingLee",
5949 
5950    Age = 22
5951 
5952 };
5953 
5954 newDB.Persons.InsertOnSubmit(newRow);
5955 
5956 newDB.SubmitChanges();
5957 
5958 var q = from x in newDB.Persons
5959 
5960      select x;
5961 
5962 //4.刪除數據庫
5963 
5964 newDB.DeleteDatabase();
5965 
5966 //5.刪除臨時目錄
5967 
5968 Directory.Delete (userTempFolder);
5969 
5970  
5971 
5972 數據庫驗證
5973  
5974 
5975 DatabaseExists方法用於 嘗試經過使用DataContext中的鏈接打開數據庫,若是成功返回true。
5976 
5977  
5978 
5979 下面代碼說明是否存在Northwind數據庫和NewCreateDB數據庫。
5980 
5981  
5982 
5983 // 檢測Northwind數據庫是否存在
5984 
5985 if (db.DatabaseExists())
5986 
5987    Console.WriteLine("Northwind數據庫存在");
5988 
5989 else
5990 
5991   Console.WriteLine("Northwind數據庫不存在");
5992 
5993 //檢測 NewCreateDB數據庫是否存在
5994 
5995 string userTempFolder =Environment.GetEnvironmentVariable("Temp");
5996 
5997 string userMDF =System.IO.Path.Combine(userTempFolder,
5998 
5999 @"NewCreateDB.mdf");
6000 
6001 NewCreateDB newDB = newNewCreateDB(userMDF);
6002 
6003 if (newDB.DatabaseExists())
6004 
6005    Console.WriteLine("NewCreateDB數據庫存在");
6006 
6007 else
6008 
6009   Console.WriteLine("NewCreateDB數據庫不存在 ");
6010 
6011  
6012 
6013 數據庫更改
6014  
6015 
6016 SubmitChanges方法計算要插入、更 新或刪除的已修改對象的集,並執行相應命令以實現對數據庫的更改。
6017 
6018  
6019 
6020 不管對象作了多少項更改,都只是在更改內存中的副本。並未對數據庫中的實際數據作任何更改。直到對DataContext顯式調用SubmitChanges,所作的更改纔會傳輸到服務器。調用時,DataContext會設法將咱們所作的更改轉換爲等效的SQL 命令。咱們也可使用本身的自定義邏輯來重寫這些操做,但提交順序是由 DataContext的一項稱做「更改處理器」的服務來協調的。事件的順序以下:
6021 
6022  
6023 
6024 當調用SubmitChanges時,LINQ to SQL會檢查已知對象的集合以肯定新實例是否已附加到它們。若是已附加,這些新實例將添加到被跟蹤對象的集合。
6025 
6026  
6027 
6028 全部具備掛起更改的對象將按照它們之間的依賴關係排序成一個對象序列。若是一個對象的更改依賴於其餘對象,則這個對象將排在其依賴項以後。
6029 
6030  
6031 
6032 在即將傳輸任何實際更改時,LINQ to SQL會啓動一個事務來封裝由各條命令組成的系列。
6033 
6034  
6035 
6036 對對象的更改會逐個轉換爲SQL命令,而後發送到服務器。
6037 
6038  
6039 
6040 若是數據庫檢測到任何錯誤,都會形成提交進程中止並引起異常。將回滾對數據庫的全部更改,就像未進行過提交同樣。DataContext 仍具備全部更改的完整記錄。
6041 
6042  
6043 
6044 下面代碼說明的是在數據庫中查詢CustomerID 爲ALFKI的顧客,而後修改其公司名稱,第一次更新並調用SubmitChanges()方法,第二次更新了數據但並未調用SubmitChanges()方法。
6045 
6046 //查詢
6047 
6048 Customer cust = db.Customers.First(c =>c.CustomerID == "ALFKI");
6049 
6050 //更新數據並調用SubmitChanges()方法
6051 
6052 cust.CompanyName = "YJingLee'sBlog";
6053 
6054 db.SubmitChanges();
6055 
6056 //更新數據沒有調用SubmitChanges()方法
6057 
6058 cust.CompanyName ="http://lyj.cnblogs.com";
6059 
6060  
6061 
6062 動態查詢
6063  
6064 
6065 使用動態查詢,這個例子用CreateQuery()方法建立一個 IQueryable<T>類型表達式輸出查詢的語句。這裏給個例子說明一下。有關動態查詢具體內容,下一篇介紹。
6066 
6067  
6068 
6069 var c1 =Expression.Parameter(typeof(Customer), "c");
6070 
6071 PropertyInfo City =typeof(Customer).GetProperty ("City");
6072 
6073 var pred =Expression.Lambda<Func<Customer, bool>>(
6074 
6075    Expression.Equal(
6076 
6077   Expression.Property(c1, City),
6078 
6079    Expression.Constant("Seattle")
6080 
6081   ), c1
6082 
6083 );
6084 
6085 IQueryable custs = db.Customers;
6086 
6087 Expression expr =Expression.Call(typeof(Queryable), "Where",
6088 
6089   new Type[] { custs.ElementType }, custs.Expression, pred);
6090 
6091 IQueryable<Customer> q =db.Customers.AsQueryable().
6092 
6093 Provider.CreateQuery<Customer>(expr);
6094 
6095  
6096 
6097 日誌
6098  
6099 
6100 Log屬性用於將SQL查詢或命令打印到TextReader。此方法對了解 LINQto SQL 功能和調試特定的問題可能頗有用。
6101 
6102  
6103 
6104 下面的示例使用Log屬性在 SQL代碼執行前在控制檯窗口中顯示此代碼。咱們能夠將此屬性與查詢、插入、更新和刪除命令一塊兒使用。
6105 
6106  
6107 
6108 //關閉日誌功能
6109 
6110 //db.Log = null;
6111 
6112 //使用日誌功能:日誌輸出到控制檯窗口
6113 
6114 db.Log = Console.Out;
6115 
6116 var q = from c in db.Customers
6117 
6118     where c.City == "London"
6119 
6120     select c;
6121 
6122 //日誌輸出到 文件
6123 
6124 StreamWriter sw = newStreamWriter(Server.MapPath ("log.txt"), true);
6125 
6126 db.Log = sw;
6127 
6128 var q = from c in db.Customers
6129 
6130     where c.City == "London"
6131 
6132     select c;
6133 
6134 sw.Close();
6135 
6136  
6137 
6138 LINQ to SQL語句(23)之動態查詢
6139 動態查詢
6140 
6141  
6142 
6143 有這樣一個場景:應用程序可能會提供一個用戶界面,用戶可使用該用戶界面指定一個或多個謂詞來篩選數據。這種狀況在編譯時不知道查詢的細節,動態查詢將十分有用。
6144 
6145  
6146 
6147 在LINQ中,Lambda表達式是許多標準查詢運算符的基礎,編譯器建立lambda表達式以捕獲基礎查詢方法(例如 Where、Select、Order By、Take While 以及其餘方法)中定義的計算。表達式目錄樹用於針對數據源的結構化查詢,這些數據源實現IQueryable<T>。例如,LINQ to SQL 提供程序實現 IQueryable<T>接口,用於查詢關係數據存儲。C#和Visual Basic編譯器會針對此類數據源的查詢編譯爲代碼,該代碼在運行時將生成一個表達式目錄樹。而後,查詢提供程序能夠遍歷表達式目錄樹數據結構,並將其轉換爲適合於數據源的查詢語言。
6148 
6149  
6150 
6151 表達式目錄樹在 LINQ中用於表示分配給類型爲Expression<TDelegate>的變量的Lambda表 達式。還可用於建立動態LINQ查詢。
6152 
6153  
6154 
6155 System.Linq.Expressions命名空間 提供用於手動生成表達式目錄樹的API。Expression類包含建立特定類型的表達 式目錄樹節點的靜態工廠方法,例如,ParameterExpression(表示一個已命名的參數表達式)或 MethodCallExpression(表示一個方法調用)。編譯器生成的表達式目錄樹的根始終在類型Expression<TDelegate>的節點中,其中 TDelegate是包含至多五個輸入參數的任何TDelegate委託;也就是說,其根節點是表示一個lambda表達式。
6156 
6157  
6158 
6159 下面幾個例子描述如何使用表達式目錄樹來建立動態LINQ查詢。
6160 
6161  
6162 
6163 1.Select
6164  
6165 
6166 下面例子說明如何使用表達式樹依據 IQueryable 數據源構造一個動態查詢,查詢出每一個顧客的ContactName,並用GetCommand方法獲取其生成SQL語句。
6167 
6168  
6169 
6170 //依據IQueryable數據 源構造一個查詢
6171 
6172 IQueryable<Customer> custs =db.Customers;
6173 
6174 //組建一個表達式樹來建立一個參數
6175 
6176 ParameterExpression param =
6177 
6178   Expression.Parameter(typeof (Customer), "c");
6179 
6180 //組建表達式樹:c.ContactName
6181 
6182 Expression selector =Expression.Property(param,
6183 
6184   typeof (Customer).GetProperty("ContactName"));
6185 
6186 Expression pred =Expression.Lambda(selector, param);
6187 
6188 //組建表達式樹:Select(c=>c.ContactName)
6189 
6190 Expression expr = Expression.Call(typeof(Queryable), "Select",
6191 
6192   new Type[] { typeof (Customer), typeof(string) },
6193 
6194   Expression.Constant(custs), pred);
6195 
6196 //使用表達式樹來生成動態查詢
6197 
6198 IQueryable<string> query =db.Customers.AsQueryable()
6199 
6200   .Provider.CreateQuery<string>(expr);
6201 
6202 //使用GetCommand方法 獲取SQL語句
6203 
6204 System.Data.Common.DbCommand cmd =db.GetCommand (query);
6205 
6206 Console.WriteLine(cmd.CommandText);
6207 
6208  
6209 
6210 生成的 SQL語句爲:
6211 
6212  
6213 
6214 SELECT [t0].[ContactName] FROM [dbo]. [Customers]AS [t0]
6215 
6216 2.Where
6217  
6218 
6219 下面一個例子是「搭建」Where用法來動態查詢城市在倫敦的顧客。
6220 
6221  
6222 
6223 IQueryable<Customer> custs =db.Customers;
6224 
6225 // 建立一個參數c
6226 
6227 ParameterExpression param =
6228 
6229    Expression.Parameter(typeof(Customer), "c");
6230 
6231 //c.City=="London"
6232 
6233 Expression left = Expression.Property(param,
6234 
6235   typeof(Customer).GetProperty ("City"));
6236 
6237 Expression right = Expression.Constant("London");
6238 
6239 Expression filter = Expression.Equal(left,right);
6240 
6241 Expression pred = Expression.Lambda(filter,param);
6242 
6243 //Where(c=>c.City=="London")
6244 
6245 Expression expr = Expression.Call(typeof(Queryable),"Where",
6246 
6247   new Type[] { typeof(Customer) },
6248 
6249   Expression.Constant(custs), pred);
6250 
6251 //生成動態查詢
6252 
6253 IQueryable<Customer> query =db.Customers.AsQueryable()
6254 
6255   .Provider.CreateQuery<Customer>(expr);
6256 
6257  
6258 
6259 生成的SQL 語句爲:
6260 
6261  
6262 
6263 SELECT [t0].[CustomerID],[t0].[CompanyName], [t0].[ContactName],
6264 
6265 [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region],
6266 
6267 [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
6268 
6269 FROM [dbo].[Customers] AS [t0] WHERE [t0].[City] = @p0
6270 
6271 -- @p0: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]
6272 
6273  
6274 
6275 3.OrderBy本例既實現排序功能又實現了過濾功能。
6276 
6277  
6278 
6279 IQueryable<Customer> custs =db.Customers;
6280 
6281 //建立一個 參數c
6282 
6283 ParameterExpression param =
6284 
6285   Expression.Parameter (typeof(Customer), "c");
6286 
6287 //c.City=="London"
6288 
6289 Expression left = Expression.Property(param,
6290 
6291    typeof(Customer).GetProperty ("City"));
6292 
6293 Expression right = Expression.Constant("London");
6294 
6295 Expression filter = Expression.Equal(left,right);
6296 
6297 Expression pred = Expression.Lambda(filter,param);
6298 
6299 //Where(c=>c.City=="London")
6300 
6301 MethodCallExpression whereCallExpression =Expression.Call(
6302 
6303    typeof(Queryable), "Where",
6304 
6305    new Type[] { typeof(Customer) },
6306 
6307    Expression.Constant(custs), pred);
6308 
6309 //OrderBy(ContactName => ContactName)
6310 
6311 MethodCallExpression orderByCallExpression= Expression.Call(
6312 
6313    typeof(Queryable), "OrderBy",
6314 
6315    new Type[] { typeof(Customer), typeof(string) },
6316 
6317    whereCallExpression,
6318 
6319    Expression.Lambda(Expression.Property
6320 
6321    (param, "ContactName"), param));
6322 
6323 //生成動態查詢
6324 
6325 IQueryable<Customer> query =db.Customers.AsQueryable()
6326 
6327    .Provider.CreateQuery<Customer> (orderByCallExpression);
6328 
6329  
6330 
6331 下面一張截圖顯示了怎麼動態生成動態查詢的過程
6332 
6333  
6334 
6335 生成的SQL語句爲:
6336 
6337  
6338 
6339 SELECT [t0].[CustomerID],[t0].[CompanyName], [t0].[ContactName],
6340 
6341 [t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region],
6342 
6343 [t0].[PostalCode], [t0].[Country], [t0].[Phone],[t0].[Fax]
6344 
6345 FROM [dbo].[Customers] AS [t0] WHERE[t0].[City] = @p0
6346 
6347 ORDER BY [t0].[ContactName]
6348 
6349 -- @p0: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]
6350 
6351 4.Union
6352 
6353  
6354 
6355 下面的例子使用表達式樹動態查詢顧客和僱員同在的城市。
6356 
6357  
6358 
6359 //e.City
6360 
6361 IQueryable<Customer> custs = db.Customers;     
6362 
6363 ParameterExpression param1 =
6364 
6365 Expression.Parameter(typeof(Customer),"e");
6366 
6367 Expression left1 =Expression.Property(param1,
6368 
6369   typeof (Customer).GetProperty("City"));
6370 
6371 Expression pred1 = Expression.Lambda(left1,param1);
6372 
6373 //c.City
6374 
6375 IQueryable<Employee> employees =db.Employees;
6376 
6377 ParameterExpression param2 =
6378 
6379 Expression.Parameter(typeof (Employee),"c");
6380 
6381 Expression left2 =Expression.Property(param2,
6382 
6383   typeof(Employee).GetProperty ("City"));
6384 
6385 Expression pred2 = Expression.Lambda(left2,param2);
6386 
6387 //Select(e=>e.City)
6388 
6389 Expression expr1 =Expression.Call(typeof(Queryable), "Select",
6390 
6391   new Type[] { typeof(Customer), typeof(string) },
6392 
6393    Expression.Constant(custs), pred1);
6394 
6395 //Select(c=>c.City)
6396 
6397 Expression expr2 =Expression.Call(typeof(Queryable), "Select",
6398 
6399   new Type[] { typeof(Employee), typeof (string) },
6400 
6401   Expression.Constant(employees), pred2);
6402 
6403 //生 成動態查詢
6404 
6405 IQueryable<string> q1 =db.Customers.AsQueryable()
6406 
6407   .Provider.CreateQuery<string>(expr1);
6408 
6409 IQueryable<string> q2 =db.Employees.AsQueryable()
6410 
6411   .Provider.CreateQuery<string>(expr2);
6412 
6413 //並集
6414 
6415 var q3 = q1.Union(q2);
6416 
6417  
6418 
6419 生成的SQL語句爲:
6420 
6421  
6422 
6423 SELECT [t2].[City]
6424 
6425 FROM (
6426 
6427   SELECT [t0].[City] FROM [dbo]. [Customers] AS [t0]
6428 
6429   UNION
6430 
6431   SELECT [t1].[City] FROM [dbo].[Employees] AS [t1]
6432 
6433   ) AS [t2]
6434 
6435  
6436 
6437 LINQ to SQL語句(24)之視圖
6438 視圖
6439 
6440  
6441 
6442 咱們使用視圖和使用數據表相似,只需將視圖從「服務器資源管理器/數據庫資源管理器」拖動到O/R 設計器上,自動能夠建立基於這些視圖的實體類。咱們能夠同操做數據表同樣來操做視圖了。這裏注意:O/R 設計器是一個簡單的對象關係映射器,由於它僅支持 1:1 映射關係。換句話說,實體類與數據庫表或視圖之間只能具備 1:1 映射關係。不支持複雜映射(例如,將一個實體類映射到多個表)。可是,能夠將一個實體類映射到一個聯接多個相關表的視圖。 下面使用NORTHWND數據庫中自帶的Invoices、QuarterlyOrders  兩個視圖爲例,寫出兩個範例。
6443 
6444  
6445 
6446 查詢:匿名類型形式
6447 
6448  
6449 
6450 咱們使用下面代碼來查詢出ShipCity 在London的發票。
6451 
6452  
6453 
6454 var q =
6455 
6456   from i in db.Invoices
6457 
6458   where i.ShipCity == "London"
6459 
6460   select new
6461 
6462   {
6463 
6464     i.OrderID,
6465 
6466      i.ProductName,
6467 
6468     i.Quantity,
6469 
6470     i.CustomerName
6471 
6472   };
6473 
6474  
6475 
6476 這裏,生成的SQL語句同使用數據表相似:
6477 
6478  
6479 
6480 SELECT [t0].[OrderID], [t0].[ProductName],[t0]. [Quantity],
6481 
6482 [t0].[CustomerName] FROM [dbo].[Invoices]AS [t0]
6483 
6484 WHERE [t0].[ShipCity] = @p0
6485 
6486 -- @p0: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]
6487 
6488 查詢:標識映射形式
6489 
6490  
6491 
6492 下例查詢出每季的訂單。
6493 
6494  
6495 
6496 var q =
6497 
6498   from qo in db.Quarterly_Orders
6499 
6500   select qo;
6501 
6502  
6503 
6504 生成SQL語句爲:
6505 
6506  
6507 
6508 SELECT [t0].[CustomerID],[t0].[CompanyName], [t0]. [City],
6509 
6510 [t0].[Country] FROM [dbo].[QuarterlyOrders] AS [t0]
6511 
6512  
6513 
6514 LINQ to SQL語句(25)之繼承
6515 繼承支持
6516 
6517  
6518 
6519 LINQ to SQL 支持單表映射,其整個繼承層次結構存儲在單個數據庫表中。該表包含整個層次結構的全部可能數據列的平展聯合。(聯合是將兩個表組合成一個表的結果,組合後的表包含任一原始表中存在的行。)每行中不適用於該行所表示的實例類型的列爲 null6520 
6521  
6522 
6523 單表映射策略是最簡單的繼承表示形式,爲許多不一樣類別的查詢提供了良好的性能特徵,若是咱們要在 LINQ to SQL 中實現這種映射,必須在繼承層次結構的根類中指定屬性 (Attribute) 和屬性 (Attribute) 的屬性 (Property)。咱們還可使用O/R設計器來映射繼承層次結構,它自動生成了代碼。
6524 
6525  
6526 
6527 下面爲了演示下面的幾個例子,咱們在O/R設計器內設計以下圖所示的類及其繼承關係。
6528 
6529  
6530 
6531 咱們學習的時候仍是看看其生成的代碼吧!
6532 
6533  
6534 
6535 具體設置映射繼承層次結構有以下幾步:
6536 
6537  
6538 
6539 根類添加TableAttribute屬性。
6540 
6541  
6542 
6543 爲層次結構中的每一個類添加InheritanceMappingAttribute屬性,一樣是添加到根類中。每一個InheritanceMappingAttribute屬性,定義一個Code屬性和一個Type屬性。Code 屬性的值顯示在數據庫表的IsDiscriminator列中,用來指示該行數據所屬的類或子類。Type屬性值指定鍵值所表示的類或子類。
6544 
6545  
6546 
6547 僅在其中一個 InheritanceMappingAttribute屬性上,添加一個IsDefault屬性用來在數據庫表 中的鑑別器值在繼承映射中不與任何Code值匹配時指定回退映射。
6548 
6549  
6550 
6551 爲 ColumnAttribute屬性添加一個IsDiscriminator屬性來表示這是保存Code值的列。
6552 
6553  
6554 
6555 下面是這張圖生成的代碼的框架(因爲生成的代碼太多,我刪除了不少「枝葉」,僅僅保留了主要的框架用於指出其實質的東西):
6556 
6557  
6558 
6559 [Table(Name = "dbo.Contacts")]
6560 
6561 [InheritanceMapping(Code ="Unknown", Type = typeof (Contact),
6562 
6563           IsDefault = true)]
6564 
6565 [InheritanceMapping(Code ="Employee", Type = typeof (EmployeeContact))]
6566 
6567 [InheritanceMapping(Code ="Supplier", Type = typeof(SupplierContact))]
6568 
6569 [InheritanceMapping(Code ="Customer", Type = typeof (CustomerContact))]
6570 
6571 [InheritanceMapping(Code ="Shipper", Type = typeof(ShipperContact))]
6572 
6573 public partial class Contact :
6574 
6575 INotifyPropertyChanging,INotifyPropertyChanged
6576 
6577 {
6578 
6579   [Column(Storage = "_ContactID",IsPrimaryKey = true,
6580 
6581   IsDbGenerated = true)]
6582 
6583   public int ContactID{ }
6584 
6585   [Column(Storage = "_ContactType",IsDiscriminator = true)]
6586 
6587   public string ContactType{ }
6588 
6589 }
6590 
6591 public abstract partial class FullContact :Contact{ }
6592 
6593 public partial class EmployeeContact :FullContact{ }
6594 
6595 public partial class SupplierContact :FullContact{ }
6596 
6597 public partial class CustomerContact :FullContact{ }
6598 
6599 public partial class ShipperContact :Contact{ }
6600 
6601  
6602 
6603 1.通常形式
6604  
6605 
6606 平常咱們常常寫的形式,對單表查詢。
6607 
6608  
6609 
6610 var cons = from c in db.Contacts
6611 
6612       select c;
6613 
6614 foreach (var con in cons) {
6615 
6616    Console.WriteLine("Company name: {0}", con.CompanyName);
6617 
6618   Console.WriteLine("Phone: {0}", con.Phone);
6619 
6620    Console.WriteLine("This is a {0}", con.GetType());
6621 
6622 }
6623 
6624  
6625 
6626 2.OfType形式
6627  
6628 
6629 這裏我僅僅讓其返回顧客的聯繫方式。
6630 
6631  
6632 
6633 var cons = from c indb.Contacts.OfType<CustomerContact>()
6634 
6635       select c;
6636 
6637  
6638 
6639 初步學習,咱們仍是看看生成的SQL語句,這樣容易理解。在 SQL語句中查詢了ContactType爲Customer的聯繫方式。
6640 
6641  
6642 
6643 SELECT [t0].[ContactType],[t0].[ContactName], [t0].[ContactTitle],
6644 
6645 [t0].[Address],[t0].[City], [t0].[Region],[t0].[PostalCode],
6646 
6647 [t0].[Country],[t0].[Fax],[t0].[ContactID], [t0].[CompanyName],
6648 
6649 [t0].[Phone] FROM [dbo].[Contacts] AS [t0]
6650 
6651 WHERE ([t0]. [ContactType] = @p0) AND([t0].[ContactType] IS NOT NULL)
6652 
6653 -- @p0: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Customer]
6654 
6655  
6656 
6657 3.IS形式
6658  
6659 
6660 這個例子查找一下發貨人的聯繫方式。
6661 
6662  
6663 
6664 var cons = from c in db.Contacts
6665 
6666       where c is ShipperContact
6667 
6668       select c;
6669 
6670  
6671 
6672 生成的SQL語句以下:查詢了ContactType爲Shipper的聯繫方式。大體一看好像很上面的同樣,其實這裏查詢出來的列多了不少。其實是Contacts表的所有字段。
6673 
6674  
6675 
6676 SELECT [t0].[ContactType],[t0].[ContactID], [t0]. [CompanyName],
6677 
6678 [t0].[Phone],[t0].[HomePage], [t0].[ContactName],
6679 
6680 [t0].[ContactTitle], [t0].[Address], [t0].[City],
6681 
6682 [t0].[Region], [t0].[PostalCode],[t0].[Country],
6683 
6684 [t0].[Fax],[t0].[PhotoPath], [t0].[Photo],[t0].[Extension]
6685 
6686 FROM [dbo].[Contacts] AS [t0] WHERE([t0].[ContactType] = @p0)
6687 
6688 AND ([t0].[ContactType] IS NOT NULL)
6689 
6690 -- @p0: Input NVarChar (Size = 7; Prec = 0;Scale = 0) [Shipper]
6691 
6692  
6693 
6694 4.AS形式
6695  
6696 
6697 這個例子就通吃了,所有查找了一番。
6698 
6699  
6700 
6701 var cons = from c in db.Contacts
6702 
6703       select c as FullContact;
6704 
6705  
6706 
6707 生成 SQL語句以下:查詢整個Contacts表。
6708 
6709  
6710 
6711 SELECT [t0]. [ContactType],[t0].[HomePage], [t0].[ContactName],
6712 
6713 [t0]. [ContactTitle],[t0].[Address],[t0].[City],
6714 
6715 [t0].[Region], [t0]. [PostalCode],[t0].[Country],
6716 
6717 [t0].[Fax], [t0].[ContactID],[t0].[CompanyName],
6718 
6719 [t0].[Phone],[t0].[PhotoPath],[t0].[Photo], [t0].[Extension]
6720 
6721 FROM [dbo].[Contacts] AS [t0]
6722 
6723  
6724 
6725 5.Cast形式
6726  
6727 
6728 使用Case形式查找出在倫敦的顧客的聯繫方式。
6729 
6730  
6731 
6732 var cons = from c in db.Contacts
6733 
6734       where c.ContactType == "Customer" &&
6735 
6736            ((CustomerContact)c).City == "London"
6737 
6738       select c;
6739 
6740  
6741 
6742 生成SQL語句以下,本身能夠看懂了。
6743 
6744  
6745 
6746 SELECT [t0].[ContactType],[t0].[ContactID], [t0]. [CompanyName],
6747 
6748 [t0].[Phone], [t0].[HomePage],[t0].[ContactName],
6749 
6750 [t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region],
6751 
6752 [t0].[PostalCode], [t0].[Country],[t0].[Fax], [t0].[PhotoPath],
6753 
6754 [t0].[Photo], [t0].[Extension]FROM [dbo].[Contacts] AS [t0]
6755 
6756 WHERE ([t0].[ContactType] = @p0) AND ([t0].[City] = @p1)
6757 
6758 -- @p0: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Customer]
6759 
6760 -- @p1: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]
6761 
6762  
6763 
6764 6.UseAsDefault形式
6765  
6766 
6767 當插入一條記錄時,使用默認的映射關係了,可是在查詢時,使用繼承的關係了。具體看看生成的SQL 語句就直截了當了。
6768 
6769  
6770 
6771 //插入一條數據默認使用正常的映射關係
6772 
6773 Contact contact = new Contact()
6774 
6775 {
6776 
6777   ContactType = null,
6778 
6779   CompanyName = "Unknown Company",
6780 
6781    Phone = "333-444-5555"
6782 
6783 };
6784 
6785 db.Contacts.InsertOnSubmit(contact);
6786 
6787 db.SubmitChanges();
6788 
6789 //查詢一條數據默認使用繼承映射關係
6790 
6791 var con =
6792 
6793   (from c in db.Contacts
6794 
6795    where c.CompanyName == "Unknown Company" &&
6796 
6797               c.Phone == "333-444-5555"
6798 
6799    select c).First();
6800 
6801  
6802 
6803 生成SQL語句以下:
6804 
6805  
6806 
6807 INSERT INTO [dbo].[Contacts]([ContactType], [CompanyName],
6808 
6809 [Phone]) VALUES (@p0, @p1, @p2)
6810 
6811 SELECT TOP (1) [t0].[ContactType], [t0].[ContactID],
6812 
6813 [t0]. [CompanyName],[t0].[Phone],[t0].[HomePage],
6814 
6815 [t0].[ContactName], [t0].[ContactTitle],[t0].[Address],
6816 
6817 [t0].[City],[t0].[Region],[t0].[PostalCode], [t0].[Country],
6818 
6819 [t0].[Fax], [t0].[PhotoPath], [t0].[Photo],[t0].[Extension]
6820 
6821 FROM [dbo].[Contacts] AS [t0]
6822 
6823 WHERE ([t0].[CompanyName] = @p0) AND([t0].[Phone] = @p1)
6824 
6825 -- @p0: Input NVarChar (Size = 15; Prec =0; Scale = 0)
6826 
6827   [Unknown Company]
6828 
6829 -- @p1: Input NVarChar (Size = 12; Prec =0; Scale = 0)
6830 
6831   [333-444-5555]
6832 
6833  
6834 
6835 7.插入新的記錄
6836  
6837 
6838 這個例子說明如何插入發貨人的聯繫方式的一條記錄。
6839 
6840  
6841 
6842 //
6843 
6844  
6845 
6846 1.在插入以前查詢一下,沒有數據
6847 var ShipperContacts =
6848 
6849   from sc in db.Contacts.OfType<ShipperContact>()
6850 
6851   where sc.CompanyName == "Northwind Shipper"
6852 
6853   select sc;
6854 
6855 //
6856 
6857  
6858 
6859 2.插入數據
6860 ShipperContact nsc = new ShipperContact()
6861 
6862 {
6863 
6864   CompanyName = "Northwind Shipper",
6865 
6866   Phone = "(123)-456-7890"
6867 
6868 };
6869 
6870 db.Contacts.InsertOnSubmit(nsc);
6871 
6872 db.SubmitChanges();
6873 
6874 //
6875 
6876  
6877 
6878 3.查詢數據,有一條記錄
6879 ShipperContacts =
6880 
6881   from sc in db.Contacts.OfType<ShipperContact>()
6882 
6883    where sc.CompanyName == "Northwind Shipper"
6884 
6885   select sc;
6886 
6887 //
6888 
6889  
6890 
6891 4.刪除記錄
6892 db.Contacts.DeleteOnSubmit (nsc);
6893 
6894 db.SubmitChanges();
6895 
6896  
6897 
6898 生成SQL語句以下:
6899 
6900  
6901 
6902 SELECT COUNT(*) AS [value] FROM[dbo].[Contacts] AS [t0]
6903 
6904 WHERE ([t0].[CompanyName] = @p0) AND([t0].[ContactType] = @p1)
6905 
6906 AND ([t0].[ContactType] IS NOT NULL)
6907 
6908 -- @p0: Input NVarChar [Northwind Shipper]
6909 
6910 -- @p1: Input NVarChar [Shipper]
6911 
6912 INSERT INTO [dbo].[Contacts]([ContactType],[CompanyName], [Phone])
6913 
6914 VALUES (@p0, @p1, @p2)
6915 
6916 -- @p0: Input NVarChar [Shipper]
6917 
6918 -- @p1: Input NVarChar [NorthwindShipper]
6919 
6920 -- @p2: Input NVarChar [(123)-456-7890]
6921 
6922 SELECT COUNT(*) AS [value] FROM[dbo].[Contacts] AS [t0]
6923 
6924 WHERE ([t0].[CompanyName] = @p0) AND([t0].[ContactType] = @p1)
6925 
6926 AND ([t0].[ContactType] IS NOT NULL)
6927 
6928 -- @p0: Input NVarChar [Northwind Shipper]
6929 
6930 -- @p1: Input NVarChar [Shipper]
6931 
6932 DELETE FROM [dbo].[Contacts] WHERE ([ContactID]= @p0) AND
6933 
6934 ([ContactType] = @p1) AND ([CompanyName] =@p2) AND ([Phone] = @p3)
6935 
6936 -- @p0: Input Int [159]
6937 
6938 -- @p1: Input NVarChar [Shipper]
6939 
6940 -- @p2: Input NVarChar [NorthwindShipper]
6941 
6942 -- @p3: Input NVarChar [(123)-456-7890]
6943 
6944 -- @p4: Input NVarChar [Unknown]
6945 
6946 -- @p5: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Supplier]
6947 
6948 -- @p6: Input NVarChar (Size = 7; Prec = 0;Scale = 0) [Shipper]
6949 
6950 -- @p7: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Employee]
6951 
6952 -- @p8: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Customer]
相關文章
相關標籤/搜索