Linq To Sql語法及實例大全


 

關於LINQ to SQL我想還有許多人還不太了解吧,下面是一些關於它的語法及操作了,提供給大家分享!

 

Linq To Sql語句(1)之Where

 

where操作

適用場景:實現過濾,查詢等功能。

 

說明:與SQL命令中的Where作用相似,都是起到范圍限定也就是過濾作用的,而判斷條件就是它后面所接的子句。

 

Where操作包括3種形式,分別為簡單形式關系條件形式First()形式。下面分別用實例舉例下:

例如:使用where篩選在倫敦的客戶

 

var q =

  from c in db.Customers

  where c.City == "London"

  select c;

 

再如:篩選1994 年或之后雇用的雇員:

 

var q =

  from e in db.Employees

  where e.HireDate >= new DateTime(1994, 1, 1)

  select e;
1.簡單形式:
 1 篩選庫存量在訂貨點水平之下但未斷貨的產品:
 2 
 3  
 4 
 5 var q =
 6 
 7   from p in db.Products
 8 
 9   where p.UnitsInStock <= p.ReorderLevel && !p.Discontinued
10 
11   select p;
12 
13  
14 
15 篩選出UnitPrice 大於10 或已停產的產品:
16 
17  
18 
19 var q =
20 
21   from p in db.Products
22 
23   where p.UnitPrice > 10m || p.Discontinued
24 
25   select p;
26 
27  
28 
29 下面這個例子是調用兩次where以篩選出UnitPrice大於10且已停產的產品。
30 
31  
32 
33 var q =
34 
35   db.Products.Where(p=>p.UnitPrice > 10m).Where(p=>p.Discontinued);
2.關系條件形式:
返回集合中的一個元素,其實質就是在SQL語句中加TOP (1)。

 

簡單用法:選擇表中的第一個發貨方。

 

Shipper shipper = db.Shippers.First();

 

元素:選擇CustomerID 為“BONAP”的單個客戶

 

Customer cust = db.Customers.First(c =>c.CustomerID == "BONAP");

 

條件:選擇運費大於 10.00 的訂單:

 

Order ord = db.Orders.First(o =>o.Freight > 10.00M);
3.First()形式:

LINQ to SQL語句(2)之Select/Distinct

[1] Select介紹1

 

[2] Select介紹2 

 

[3] Select介紹3和 Distinct介紹

 Select/Distinct操作符

 適用場景:o(∩_∩) o…查詢唄。

 

說明:和SQL命令中的select作用相似但位置不同,查詢表達式中的select及所接子句是放在表達式最后並把子句中的變量也就是結果返回回來;延遲。

 

Select/Distinct操作包括9種形式,分別為簡單用 法、匿名類型形式、條件形式、指定類型形式、篩選形式、整形類型形式、嵌套類型形式、本地方法調用形式、Distinct形式。

 1 這個示例返回僅含客戶聯系人姓名的序列。
 2 
 3  
 4 
 5 var q =
 6 
 7   from c in db.Customers
 8 
 9   select c.ContactName;
10 
11  
12 
13 注意:這個語句只是一個聲明或者一個描述,並沒有真正把數據取出來,只有當你需要該數據的時候,它才會執行這個語句,這就是延遲加載(deferred loading)。如果,在聲明的時候就返回的結果集是對象的集合。你可以使用ToList() 或ToArray()方法把查詢結果先進行保存,然后再對這個集合進行查詢。當然延遲加載(deferred loading)可以像拼接SQL語句那樣拼接查詢語法,再執行它。
1.簡單用法:
 1 說明:匿名類型是C#3.0中新特性。其實質是編譯器根據我們自定義自動產生一個匿名的類來幫助我們實現臨時變量的儲存。匿名類型還依賴於另外一個特性:支持根據property來創建對象。比如,var d = new { Name = "s" };編譯器自動產生一個有property叫做Name的匿名類,然后按這 個類型分配內存,並初始化對象。但是var d = new {"s"};是編譯不 通過的。因為,編譯器不知道匿名類中的property的名字。例如stringc = "d";var d = new { c}; 則是可以通過編譯的。編譯器會創建一個叫 做匿名類帶有叫c的property。
 2 
 3  
 4 
 5 例如下例:new {c,ContactName,c.Phone};ContactName和Phone都是在映射文件中定義與表中字 段相對應的property。編譯器讀取數據並創建對象時,會創建一個匿名類,這個 類有兩個屬性,為ContactName和Phone,然后根據數據初始化對象。另外編譯器 還可以重命名property的名字。
 6 
 7  
 8 
 9 var q =
10 
11   from c in db.Customers
12 
13   select new {c.ContactName, c.Phone};
14 
15  
16 
17 上面語句描述:使用 SELECT 和匿名類型返回僅含客戶聯系人姓名和電話號碼的序列
18 
19  
20 
21 var q =
22 
23   from e in db.Employees
24 
25   select new
26 
27   {
28 
29     Name = e.FirstName + " " + e.LastName,
30 
31     Phone = e.HomePhone
32 
33   };
34 
35  
36 
37 上面語句描述:使用SELECT和匿名類型返回僅含雇員姓名和電話號碼的序列,並將 FirstName和LastName字段合並為一個字段“Name”,此外在所得的序列中將HomePhone字段重命名為Phone。
38 
39  
40 
41 var q =
42 
43   from p in db.Products
44 
45   select new
46 
47   {
48 
49      p.ProductID,
50 
51     HalfPrice = p.UnitPrice / 2
52 
53   };
54 
55  
56 
57 上面語句描述:使用SELECT和匿名類型返回所有產品的ID以及 HalfPrice(設置為產品單價除以2所得的值)的序列。
2.匿名類型形式:
 1 說明:生成SQL語句為:case when condition then else 2 
 3  
 4 
 5 var q =
 6 
 7   from p in db.Products
 8 
 9   select new
10 
11   {
12 
13     p.ProductName,
14 
15     Availability =
16 
17      p.UnitsInStock - p.UnitsOnOrder < 0 ?
18 
19     "Out Of Stock" : "In Stock"
20 
21   };
22 
23  
24 
25 上面語句描述:使用SELECT和條件語句返回產品名稱和產品供貨狀態的序列。
3.條件形式:
 1 說明:該形式返回你自定義類型的對象集。
 2 
 3  
 4 
 5 var q =
 6 
 7   from e in db.Employees
 8 
 9   select new Name
10 
11    {
12 
13     FirstName = e.FirstName,
14 
15     LastName = e.LastName
16 
17   };
18 
19  
20 
21 上面語句描述:使用SELECT和已知類型返回雇員姓名的序列。
4.指定類型形式:
 1 說明:結合where使用,起到過濾作用。
 2 
 3  
 4 
 5 var q =
 6 
 7   from c in db.Customers
 8 
 9    where c.City == "London"
10 
11   select c.ContactName;
12 
13  
14 
15 上面語句描述:使用SELECT和WHERE返回僅含倫敦客戶聯系人姓名的序列。
5.篩選形式:
 1 說明:其select操作使用了匿名對象,而這個匿名對象中,其屬性也是個匿名對象。
 2 
 3  
 4 
 5 var q =
 6 
 7   from c in db.Customers
 8 
 9   select new {
10 
11     c.CustomerID,
12 
13     CompanyInfo = new {c.CompanyName, c.City, c.Country},
14 
15     ContactInfo = new {c.ContactName, c.ContactTitle}
16 
17   };
18 
19  
20 
21 語句描述:使用 SELECT 和匿名類型返回有關客戶的數據的整形子集。查詢顧客的ID和公司信息(公司名稱,城市,國家)以及聯系信息(聯系人和職位)。
6.shaped形式(整形類型):
 1 說明:返回的對象集中的每個對象DiscountedProducts屬性中,又包含一個集合。也就是每個對象也是一個集合類。
 2 
 3  
 4 
 5 var q =
 6 
 7   from o in db.Orders
 8 
 9   select new {
10 
11      o.OrderID,
12 
13     DiscountedProducts =
14 
15       from od in o.OrderDetails
16 
17       where od.Discount > 0.0
18 
19       select od,
20 
21     FreeShippingDiscount = o.Freight
22 
23   };
24 
25  
26 
27 語句描述:使用嵌套查詢返回所有訂單及其OrderID 的序列、打折訂單中項目的子序列以及免送貨所省下的金額。
7.嵌套類型形式:
 1 這個例子在查詢中調用本地方法 PhoneNumberConverter將電話號碼轉換為國際格式。
 2 
 3  
 4 
 5 var q = from c in db.Customers
 6 
 7      where c.Country == "UK" || c.Country == "USA"
 8 
 9      select new
10 
11      {
12 
13        c.CustomerID,
14 
15        c.CompanyName,
16 
17        Phone = c.Phone,
18 
19        InternationalPhone =
20 
21        PhoneNumberConverter(c.Country, c.Phone)
22 
23      };
24 
25  
26 
27 PhoneNumberConverter方法如下:
28 
29  
30 
31 public string PhoneNumberConverter(stringCountry, string Phone)
32 
33 {
34 
35   Phone = Phone.Replace(" ", "").Replace(")", ")-");
36 
37   switch (Country)
38 
39    {
40 
41     case "USA":
42 
43       return "1- " + Phone;
44 
45     case "UK":
46 
47        return "44-" + Phone;
48 
49     default:
50 
51       return Phone;
52 
53   }
54 
55 }
56 
57  
58 
59 下面也是使用了這個方法將電話號碼轉換為國際格式並創建XDocument
60 
61  
62 
63 XDocument doc = new XDocument(
64 
65   new XElement("Customers", from c in db.Customers
66 
67        where c.Country == "UK" || c.Country == "USA"
68 
69        select (new XElement ("Customer",
70 
71            new XAttribute ("CustomerID", c.CustomerID),
72 
73            new XAttribute("CompanyName", c.CompanyName),
74 
75            new XAttribute("InterationalPhone",
76 
77             PhoneNumberConverter(c.Country, c.Phone))
78 
79            ))));
8.本地方法調用形式(LocalMethodCall):
 1 說明:篩選字段中不相同的值。用於查詢不重復的結果集。生成SQL語句為:SELECT DISTINCT [City] FROM [Customers]
 2 
 3  
 4 
 5 var q = (
 6 
 7   from c in db.Customers
 8 
 9   select c.City )
10 
11   .Distinct();
12 
13  
14 
15 語句描述:查詢顧客覆蓋的國家。
9.Distinct形式:

LINQ to SQL語句(3)之Count/Sum/Min/Max/Avg

[1] Count/Sum講解

 

[2] Min講解

 

[3] Max講解

 

[4] Average和Aggregate講解

 

Count/Sum/Min/Max/Avg操作符

 

適用場景:統計數據吧,比如統計一些數據的個數,求和,最小值,最大值,平均數。

 

 

 1 Count  2 
 3  
 4 
 5 說明:返回集合中的元素個數,返回INT類型;不延遲。生成 SQL語句為:SELECT COUNT(*) FROM  6 
 7  
 8 
 9 1.簡單形式:  10 
 11  
 12 
 13 得到數據庫中客戶的數量:  14 
 15  
 16 
 17 var q = db.Customers.Count();  18 
 19  
 20 
 21 2.帶條件形式:  22 
 23  
 24 
 25 得到數據庫中未斷貨產品的數量:  26 
 27  
 28 
 29 var q = db.Products.Count(p =>!p.Discontinued);  30 
 31  
 32 
 33 LongCount  34 
 35  
 36 
 37 說明:返回集合中的元素個數,返回LONG類型;不延遲。對於元素個數較多的集合可視情況可以選用LongCount來統計元素個數,它返回long類型,比較精確。生成 SQL語句為:SELECT COUNT_BIG(*) FROM  38 
 39  
 40 
 41 var q = db.Customers.LongCount();  42 
 43  
 44 
 45 Sum  46 
 47  
 48 
 49 說明:返回集合中數值類型元素之和,集合應為INT類型集合;不延遲。生成SQL語句為:SELECT SUM(…) FROM  50 
 51  
 52 
 53 1.簡單形式:  54 
 55  
 56 
 57 得到所有訂單的總運費:  58 
 59  
 60 
 61 var q = db.Orders.Select(o =>o.Freight).Sum();  62 
 63  
 64 
 65 2.映射形式:  66 
 67  
 68 
 69 得到所有產品的訂貨總數:  70 
 71  
 72 
 73 var q = db.Products.Sum(p =>p.UnitsOnOrder);  74 
 75 Min  76 
 77 說明:返回集合中元素的最小值;不延遲。生成SQL語句為:SELECT MIN(…) FROM  78 
 79 1.簡單形式:  80 
 81 查找任意產品的最低單價:  82 
 83 var q = db.Products.Select(p => p.UnitPrice).Min();  84 
 85  
 86 
 87 2.映射形式:  88 
 89  
 90 
 91 查找任意訂單的最低運費:  92 
 93  
 94 
 95 var q = db.Orders.Min(o => o.Freight);  96 
 97  
 98 
 99  
100 
101 3.元素: 102 
103  
104 
105 查找每個類別中單價最低的產品: 106 
107  
108 
109 var categories =
110 
111   from p in db.Products 112 
113   group p by p.CategoryID into g 114 
115   select new { 116 
117     CategoryID = g.Key, 118 
119      CheapestProducts =
120 
121       from p2 in g 122 
123        where p2.UnitPrice == g.Min(p3 => p3.UnitPrice) 124 
125        select p2 126 
127   }; 128 
129 Max 130 
131 說明:返回集合中元素的最大值;不延遲。生成SQL語句為:SELECT MAX(…) FROM 132 
133 1.簡單形式: 134 
135 查找任意雇員的最近雇用日期: 136 
137 var q = db.Employees.Select(e => e.HireDate).Max(); 138 
139  
140 
141 2.映射形式: 142 
143  
144 
145 查找任意產品的最大庫存量: 146 
147  
148 
149 var q = db.Products.Max(p =>p.UnitsInStock); 150 
151  
152 
153 3.元素: 154 
155  
156 
157 查找每個類別中單價最高的產品: 158 
159  
160 
161 var categories =
162 
163   from p in db.Products 164 
165    group p by p.CategoryID into g 166 
167   select new { 168 
169      g.Key, 170 
171     MostExpensiveProducts =
172 
173       from p2 in g 174 
175       where p2.UnitPrice == g.Max(p3 => p3.UnitPrice) 176 
177       select p2 178 
179   }; 180 
181 Average 182 
183 說明:返回集合中的數值類型元素的平均值。集合應為數字類型集合,其返回值類型為double;不延遲。生成SQL語句為:SELECT AVG(…) FROM 184 
185 1.簡單形式: 186 
187 得到所有訂單的平均運費: 188 
189 var q = db.Orders.Select(o =>o.Freight).Average(); 190 
191  
192 
193 2.映射形式: 194 
195  
196 
197 得到所有產品的平均單價: 198 
199  
200 
201 var q = db.Products.Average(p => p.UnitPrice); 202 
203  
204 
205 3.元素: 206 
207  
208 
209 查找每個類別中單價高於該類別平均單價的產品: 210 
211  
212 
213 var categories =
214 
215   from p in db.Products 216 
217   group p by p.CategoryID into g 218 
219   select new { 220 
221     g.Key, 222 
223     ExpensiveProducts =
224 
225       from p2 in g 226 
227       where p2.UnitPrice > g.Average (p3 => p3.UnitPrice) 228 
229       select p2 230 
231   }; 232 
233  
234 
235 Aggregate 236 
237  
238 
239 說明:根據輸入的表達式獲取聚合值;不延遲。即是說:用一個種子值與當前元素通過指定的函數來進行對比來遍歷集合中的元素,符合條件的元素保留下來。如果沒有指定種子值的話,種子值默認為集合的第一個元素。
Count/Sum/Min/Max/Avg

 

LINQ to SQL語句(4)之Join

Join操作符

適用場景:在我們表關系中有一對一關系,一對多關系,多對多關系等。對各個表之間的關系,就用這些實現對多個表的操作。

 

說明:在Join操作中,分別為Join(Join查詢), SelectMany(Select一對多選擇) 和GroupJoin(分組Join查詢)。

 

該擴展方法對兩個序列中鍵匹配的元素進行inner join操作

 

SelectMany

 

說明:我們在寫查詢語句時,如果被翻譯成SelectMany需要滿足2個條件。1:查詢語句中沒有join和into,2:必須出現EntitySet。在我們表關系中有一對一關系,一對多關系,多對多關系等,下面分別介紹一下。

 

  1 1.一對多關系(1 to Many):
  2 
  3  
  4 
  5 var q =
  6 
  7   from c in db.Customers
  8 
  9   from o in c.Orders
 10 
 11   where c.City == "London"
 12 
 13   select o;
 14 
 15  
 16 
 17 語句描述:Customers與Orders是一對多關系。即Orders在Customers類中以 EntitySet形式出現。所以第二個from是從c.Orders而不是db.Orders里進行篩選。這個例子在From子句中使用外鍵導航選擇倫敦客戶的所有訂單。
 18 
 19  
 20 
 21 var q =
 22 
 23   from p in db.Products
 24 
 25   where p.Supplier.Country == "USA" &&p.UnitsInStock == 0
 26 
 27   select p;
 28 
 29  
 30 
 31 語句描述:這一句使用了 p.Supplier.Country條件,間接關聯了Supplier表。這個例子在Where子句中使用外鍵導航篩選其供應商在美國且缺貨的產品。生成SQL語句為:
 32 
 33  
 34 
 35 SELECT [t0].[ProductID],[t0].[ProductName], [t0]. [SupplierID],
 36 
 37 [t0].[CategoryID],[t0].[QuantityPerUnit],[t0].[UnitPrice],
 38 
 39 [t0].[UnitsInStock],[t0].[UnitsOnOrder],[t0]. [ReorderLevel],
 40 
 41 [t0].[Discontinued] FROM [dbo].[Products]AS [t0]
 42 
 43 LEFT OUTER JOIN [dbo].[Suppliers] AS [t1]ON
 44 
 45 [t1]. [SupplierID] = [t0].[SupplierID]
 46 
 47 WHERE ([t1].[Country] = @p0) AND([t0].[UnitsInStock] = @p1)
 48 
 49 -- @p0: Input NVarChar (Size = 3; Prec = 0;Scale = 0) [USA]
 50 
 51 -- @p1: Input Int (Size = 0; Prec = 0;Scale = 0) [0]
 52 
 53  
 54 
 55 2.多對多關系(Many to Many):
 56 
 57  
 58 
 59 var q =
 60 
 61   from e in db.Employees
 62 
 63   from et in e.EmployeeTerritories
 64 
 65   where e.City == "Seattle"
 66 
 67   select new
 68 
 69   {
 70 
 71     e.FirstName,
 72 
 73      e.LastName,
 74 
 75     et.Territory.TerritoryDescription
 76 
 77   };
 78 
 79  
 80 
 81 說明:多對多關系一般會涉及三個表(如果有一個表是自關聯的,那有可能只有2個表)。這一句語句涉及Employees, EmployeeTerritories, Territories三個表。它們的關系是1:M:1。Employees 和Territories沒有很明確的關系。
 82 
 83  
 84 
 85 語句描述:這個例子在From子句中使用外鍵導航篩選在西雅圖的雇員,同時列出其所在地區。這條生成SQL語句為:
 86 
 87  
 88 
 89 SELECT [t0].[FirstName], [t0].[LastName],[t2]. [TerritoryDescription]
 90 
 91 FROM [dbo].[Employees] AS [t0] CROSS JOIN[dbo].[EmployeeTerritories]
 92 
 93 AS [t1] INNER JOIN [dbo]. [Territories] AS[t2] ON
 94 
 95 [t2].[TerritoryID] = [t1].[TerritoryID]
 96 
 97 WHERE ([t0].[City] = @p0) AND([t1].[EmployeeID] = [t0]. [EmployeeID])
 98 
 99 -- @p0: Input NVarChar (Size = 7; Prec = 0;Scale = 0) [Seattle]
100 
101  
102 
103  
104 
105 3.自聯接關系:
106 
107  
108 
109 var q =
110 
111   from e1 in db.Employees
112 
113   from e2 in e1.Employees
114 
115   where e1.City == e2.City
116 
117   select new {
118 
119     FirstName1 = e1.FirstName, LastName1 = e1.LastName,
120 
121     FirstName2 = e2.FirstName, LastName2 = e2.LastName,
122 
123     e1.City
124 
125   };
126 
127  
128 
129 語句描述:這個例子在select 子句中使用外鍵導航篩選成對的雇員,每對中一個雇員隸屬於另一個雇員,且兩個雇員都來自相同城市。生成SQL語句為:
130 
131  
132 
133 SELECT [t0].[FirstName] AS [FirstName1],[t0].[LastName] AS
134 
135 [LastName1],[t1].[FirstName] AS[FirstName2], [t1].[LastName] AS
136 
137 [LastName2],[t0].[City] FROM[dbo].[Employees] AS [t0],
138 
139 [dbo].[Employees] AS [t1] WHERE([t0].[City] = [t1]. [City]) AND
140 
141 ([t1].[ReportsTo] = [t0].[EmployeeID])
142 
143 GroupJoin
144 
145  
146 
147 像上面所說的,沒有join和into,被翻譯成 SelectMany,同時有join和into時,那么就被翻譯為GroupJoin。在這里into的概念是對其結果進行重新命名。
148 
149  
150 
151 1.雙向聯接(Two way join):
152 
153  
154 
155 此示例顯式聯接兩個表並從這兩個表投影出結果:
156 
157  
158 
159 var q =
160 
161    from c in db.Customers
162 
163   join o in db.Orders on c.CustomerID
164 
165   equals o.CustomerID into orders
166 
167   select new
168 
169    {
170 
171     c.ContactName,
172 
173     OrderCount = orders.Count ()
174 
175   };
176 
177  
178 
179 說明:在一對多關系中,左邊是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返回值作為字段值。如圖所示:
180 
181  
182 
183  
184 
185  
186 
187 生成SQL語句為:
188 
189  
190 
191 SELECT [t0].[ContactName], (
192 
193   SELECT COUNT(*)
194 
195   FROM [dbo].[Orders] AS [t1]
196 
197    WHERE [t0].[CustomerID] = [t1].[CustomerID]
198 
199 ) AS [OrderCount]
200 
201 FROM [dbo].[Customers] AS [t0]
202 
203  
204 
205 2.三向聯接(There way join):
206 
207  
208 
209 此示例顯式聯接三個表並分別從每個表投影出結果:
210 
211  
212 
213 var q =
214 
215   from c in db.Customers
216 
217   join o in db.Orders on c.CustomerID
218 
219   equals o.CustomerID into ords
220 
221   join e in db.Employees on c.City
222 
223   equals e.City into emps
224 
225   select new
226 
227   {
228 
229     c.ContactName,
230 
231     ords = ords.Count(),
232 
233     emps = emps.Count()
234 
235   };
236 
237  
238 
239 生成SQL語句為:
240 
241  
242 
243 SELECT [t0]. [ContactName], (
244 
245   SELECT COUNT(*)
246 
247   FROM [dbo].[Orders] AS [t1]
248 
249   WHERE [t0].[CustomerID] = [t1].[CustomerID]
250 
251 ) AS [ords], (
252 
253 SELECT COUNT(*)
254 
255   FROM [dbo].[Employees] AS [t2]
256 
257   WHERE [t0].[City] = [t2].[City]
258 
259 ) AS [emps]
260 
261 FROM [dbo].[Customers] AS [t0]
262 
263  
264 
265 3.左外部聯接(Left Outer Join):
266 
267  
268 
269 此示例說明如何通過使用此示例說明如何通過使用 DefaultIfEmpty() 獲取左外部聯接。在雇員沒有訂單時,DefaultIfEmpty()方法返回null:
270 
271  
272 
273 var q =
274 
275   from e in db.Employees
276 
277    join o in db.Orders on e equals o.Employee into ords
278 
279   from o in ords.DefaultIfEmpty()
280 
281   select new
282 
283   {
284 
285      e.FirstName,
286 
287     e.LastName,
288 
289     Order = o
290 
291    };
292 
293  
294 
295 說明:以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就是一個集合。
296 
297  
298 
299 4.投影的Let賦值(Projectedlet assignment):
300 
301  
302 
303 說明:let語句是重命名。let位於第一個from和select語句之間。
304 
305  
306 
307 這個例子從聯接投影出最終“Let”表達式:
308 
309  
310 
311 var q =
312 
313   from c in db.Customers
314 
315   join o in db.Orders on c.CustomerID
316 
317    equals o.CustomerID into ords
318 
319   let z = c.City + c.Country
320 
321   from o in ords
322 
323   select new
324 
325   {
326 
327      c.ContactName,
328 
329     o.OrderID,
330 
331     z
332 
333   };
334 
335  
336 
337 5.組合鍵(Composite Key):
338 
339  
340 
341 這個例子顯示帶有組合鍵的聯接:
342 
343  
344 
345 var q =
346 
347   from o in db.Orders
348 
349   from p in db.Products
350 
351   join d in db.OrderDetails
352 
353     on new
354 
355     {
356 
357       o.OrderID,
358 
359        p.ProductID
360 
361     } equals
362 
363       new
364 
365       {
366 
367         d.OrderID,
368 
369          d.ProductID
370 
371       }
372 
373     into details
374 
375   from d in details
376 
377   select new
378 
379   {
380 
381     o.OrderID,
382 
383     p.ProductID,
384 
385     d.UnitPrice
386 
387   };
388 
389  
390 
391 說明:使用三個表,並且用匿名類來說明:使用三個表,並且用匿名類來表示它們之間的關系。它們之間的關系不能用一個鍵描述清楚,所以用匿名類,來表示組合鍵。還有一種是兩個表之間是用組合鍵表示關系的,不需要使用匿名類。
Json

 

LINQ to SQL語句(5)之Order By

Order By操作

 

適用場景:對查詢出的語句進行排序,比如按時間排序等等。

 

 

 

說明:按指定表達式對集合排序;延遲,:按指定表達式對集合排序;延遲,默認是升序,加上descending表示降序,對應的擴展方法是 OrderBy和OrderByDescending

 

  1 1.簡單形式
  2 
  3  
  4 
  5 這個例子使用 orderby 按雇用日期對雇員進行排序:
  6 
  7  
  8 
  9 var q =
 10 
 11   from e in db.Employees
 12 
 13   orderby e.HireDate
 14 
 15   select e;
 16 
 17  
 18 
 19 說明:默認為升序
 20 
 21  
 22 
 23 2.帶條件形式
 24 
 25  
 26 
 27 注意:Where 和Order By的順序並不重要。而在T-SQL中,Where和Order By有嚴格的位置限制。
 28 
 29  
 30 
 31 var q =
 32 
 33   from o in db.Orders
 34 
 35   where o.ShipCity == "London"
 36 
 37   orderby o.Freight
 38 
 39    select o;
 40 
 41  
 42 
 43 語句描述:使用where和orderby按運費進行排序。
 44 
 45  
 46 
 47 3.降序排序
 48 
 49  
 50 
 51 var q =
 52 
 53   from p in db.Products
 54 
 55   orderby p.UnitPrice descending
 56 
 57   select p;
 58 
 59  
 60 
 61  
 62 
 63 4.ThenBy
 64 
 65  
 66 
 67 語句描述:使用復合的 orderby 對客戶進行排序,進行排序:
 68 
 69  
 70 
 71 var q =
 72 
 73   from c in db.Customers
 74 
 75   orderby c.City, c.ContactName
 76 
 77   select c;
 78 
 79  
 80 
 81 說明:按多個表達式進行排序,例如先按City排序,當City相同時,按ContactName排序。這一句用Lambda表達式像這樣寫:
 82 
 83  
 84 
 85 var q =
 86 
 87   .OrderBy(c => c.City)
 88 
 89   .ThenBy(c => c.ContactName).ToList();
 90 
 91  
 92 
 93 在T-SQL中沒有 ThenBy語句,其依然翻譯為OrderBy,所以也可以用下面語句來表達:
 94 
 95  
 96 
 97 var q =
 98 
 99   db.Customers
100 
101   .OrderBy(c => c.ContactName)
102 
103   .OrderBy(c => c.City).ToList ();
104 
105  
106 
107 所要注意的是,多個OrderBy操作時,級連方式是按逆序。對於降序的,用相應的降序操作符替換即可。
108 
109  
110 
111 var q =
112 
113    db.Customers
114 
115   .OrderByDescending(c => c.City)
116 
117   .ThenByDescending(c => c.ContactName).ToList();
118 
119  
120 
121 需要說明的是,OrderBy操作,不支持按type排序,也不支持匿名類。比如
122 
123  
124 
125 var q =
126 
127   db.Customers
128 
129   .OrderBy(c => new
130 
131   {
132 
133     c.City,
134 
135     c.ContactName
136 
137   }).ToList();
138 
139  
140 
141 會被拋出異常。錯誤是前面的操作有匿名類,再跟OrderBy時,比較的是類別。比如
142 
143  
144 
145 var q =
146 
147    db.Customers
148 
149   .Select(c => new
150 
151   {
152 
153      c.City,
154 
155     c.Address
156 
157   })
158 
159   .OrderBy(c => c).ToList();
160 
161  
162 
163 如果你想使用OrderBy(c => c),其前提條件是,前面步驟中,所產生的對象的類別必須為C#語言的基本類型。比如下句,這里 City為string類型。
164 
165  
166 
167 var q =
168 
169   db.Customers
170 
171    .Select(c => c.City)
172 
173   .OrderBy(c => c).ToList ();
174 
175  
176 
177  
178 
179 5.ThenByDescending
180 
181  
182 
183 這兩個擴展方式都是用在 OrderBy/OrderByDescending之后的,第一個ThenBy/ThenByDescending擴展方法 作為第二位排序依據,第二個ThenBy/ThenByDescending則作為第三位排序依據 ,以此類推
184 
185  
186 
187 var q =
188 
189   from o in db.Orders
190 
191    where o.EmployeeID == 1
192 
193   orderby o.ShipCountry, o.Freight descending
194 
195   select o;
196 
197  
198 
199 語句描述:使用orderby先按發往國家再按運費從高到低的順序對 EmployeeID 1 的訂單進行排序。
200 
201  
202 
203 6. 帶GroupBy形式
204 
205  
206 
207 var q =
208 
209   from p in db.Products
210 
211    group p by p.CategoryID into g
212 
213   orderby g.Key
214 
215   select new {
216 
217     g.Key,
218 
219     MostExpensiveProducts =
220 
221       from p2 in g
222 
223       where p2.UnitPrice == g.Max(p3 => p3.UnitPrice)
224 
225       select p2
226 
227   };
228 
229  
230 
231 語句描述:使用orderby、Max 和 Group By 得出每種類別中單價最高的產品,並按 CategoryID 對這組產品進行排序。
order by 排序

 

LINQ to SQL語句(6)之GroupBy/Having

Group By/Having操作符

 

適用場景:分組數據,為我們查找數據縮小范圍。

 

 

 

說明:分配並返回對傳入參數進行分組操作后的可枚舉對象。分組;延遲

 

  1 1.簡單形式:
  2 
  3  
  4 
  5 var q =
  6 
  7   from p in db.Products
  8 
  9   group p by p.CategoryID into g
 10 
 11   select g;
 12 
 13  
 14 
 15 語句描述:使用Group By按CategoryID划分產品。
 16 
 17  
 18 
 19 說明:from p in db.Products 表示從表中將產品對象取出來。group p by p.CategoryID into g表示對p按CategoryID字段歸類。其結果命名為g,一旦重 新命名,p的作用域就結束了,所以,最后select時,只能select g。當然,也不必重新命名可以這樣寫:
 20 
 21  
 22 
 23 var q =
 24 
 25   from p in db.Products
 26 
 27   group p by p.CategoryID;
 28 
 29  
 30 
 31 我們用示意圖表示:
 32 
 33  
 34 
 35  
 36 
 37 如果想遍歷某類別中所有記錄,這樣:
 38 
 39  
 40 
 41 foreach (var gp in q)
 42 
 43 {
 44 
 45   if (gp.Key == 2)
 46 
 47   {
 48 
 49      foreach (var item in gp)
 50 
 51     {
 52 
 53       //do something
 54 
 55     }
 56 
 57   }
 58 
 59 }
 60 
 61  
 62 
 63 2.Select匿名類:
 64 
 65  
 66 
 67 var q =
 68 
 69   from p in db.Products
 70 
 71   group p by p.CategoryID into g
 72 
 73   select new { CategoryID = g.Key, g };
 74 
 75  
 76 
 77 說明:在這句LINQ語句中,有2個property:CategoryID和g。這個匿名類,其實質是對返回結果集重新進行了包裝。把g的property封裝成一個完整的分組。如下圖所示:
 78 
 79  
 80 
 81  
 82 
 83 如果想遍歷某匿名類中所有記錄,要這么做:
 84 
 85  
 86 
 87 foreach (var gp in q)
 88 
 89 {
 90 
 91   if (gp.CategoryID == 2)
 92 
 93   {
 94 
 95     foreach (var item in gp.g)
 96 
 97     {
 98 
 99       //do something
100 
101     }
102 
103   }
104 
105 }
106 
107  
108 
109 3.最大值
110 
111  
112 
113 var q =
114 
115   from p in db.Products
116 
117   group p by p.CategoryID into g
118 
119   select new {
120 
121     g.Key,
122 
123     MaxPrice = g.Max(p => p.UnitPrice)
124 
125   };
126 
127  
128 
129 語句描述:使用Group By和Max查找每個CategoryID的最高單價。
130 
131  
132 
133 說明:先按CategoryID歸類,判斷各個分類產品中單價最大的 Products。取出CategoryID值,並把UnitPrice值賦給MaxPrice。
134 
135  
136 
137 4.最小值
138 
139  
140 
141 var q =
142 
143   from p in db.Products
144 
145   group p by p.CategoryID into g
146 
147   select new {
148 
149     g.Key,
150 
151     MinPrice = g.Min(p => p.UnitPrice)
152 
153   };
154 
155  
156 
157 語句描述:使用Group By和Min查找每個CategoryID的最低單價。
158 
159  
160 
161 說明:先按CategoryID歸類,判斷各個分類產品中單價最小的 Products。取出CategoryID值,並把UnitPrice值賦給MinPrice。
162 
163  
164 
165 5.平均值
166 
167  
168 
169 var q =
170 
171   from p in db.Products
172 
173   group p by p.CategoryID into g
174 
175   select new {
176 
177     g.Key,
178 
179     AveragePrice = g.Average(p => p.UnitPrice)
180 
181   };
182 
183  
184 
185 語句描述:使用Group By和Average得到每個CategoryID的平均單價。
186 
187  
188 
189 說明:先按CategoryID歸類,取出CategoryID值和各個分類產品中單價的平均值。
190 
191  
192 
193 6.求和
194 
195  
196 
197 var q =
198 
199   from p in db.Products
200 
201   group p by p.CategoryID into g
202 
203   select new {
204 
205     g.Key,
206 
207     TotalPrice = g.Sum(p => p.UnitPrice)
208 
209   };
210 
211  
212 
213 語句描述:使用Group By和Sum得到每個CategoryID 的單價總計。
214 
215  
216 
217 說明:先按CategoryID歸類,取出 CategoryID值和各個分類產品中單價的總和。
218 
219  
220 
221 7.計數
222 
223  
224 
225 var q =
226 
227   from p in db.Products
228 
229   group p by p.CategoryID into g
230 
231   select new {
232 
233     g.Key,
234 
235     NumProducts = g.Count()
236 
237   };
238 
239  
240 
241 語句描述:使用Group By和Count得到每個CategoryID中產品的數量。
242 
243  
244 
245 說明:先按CategoryID歸類,取出 CategoryID值和各個分類產品的數量。
246 
247  
248 
249 8.帶條件計數
250 
251  
252 
253 var q =
254 
255   from p in db.Products
256 
257   group p by p.CategoryID into g
258 
259   select new {
260 
261     g.Key,
262 
263     NumProducts = g.Count(p => p.Discontinued)
264 
265   };
266 
267  
268 
269 語句描述:使用Group By和Count得到每個CategoryID中斷貨產品的數量。
270 
271  
272 
273 說明:先按 CategoryID歸類,取出CategoryID值和各個分類產品的斷貨數量。Count函數里,使用了Lambda表達式,Lambda表達式中的p,代表這個組里的一個元素或對象,即某一個產品。
274 
275  
276 
277 9.Where限制
278 
279  
280 
281 var q =
282 
283   from p in db.Products
284 
285   group p by p.CategoryID into g
286 
287   where g.Count() >= 10
288 
289   select new {
290 
291     g.Key,
292 
293     ProductCount = g.Count()
294 
295   };
296 
297  
298 
299 語句描述:根據產品的―ID分組,查詢產品數量大於10的ID和產品數量。這個示例在Group By子句后使用Where子句查找所有至少有10種產品的類別。
300 
301  
302 
303 說明:在翻譯成SQL 語句時,在最外層嵌套了Where條件。
304 
305  
306 
307 10.多列(Multiple Columns)
308 
309  
310 
311 var categories =
312 
313   from p in db.Products
314 
315    group p by new
316 
317   {
318 
319     p.CategoryID,
320 
321      p.SupplierID
322 
323   }
324 
325     into g
326 
327     select new
328 
329       {
330 
331         g.Key,
332 
333         g
334 
335       };
336 
337  
338 
339 語句描述:使用Group By按CategoryID和 SupplierID將產品分組。
340 
341  
342 
343 說明:既按產品的分類,又按供應商分類。在 by后面,new出來一個匿名類。這里,Key其實質是一個類的對象,Key包含兩個 Property:CategoryID、SupplierID。用g.Key.CategoryID可以遍歷CategoryID 的值。
344 
345  
346 
347 11.表達式(Expression)
348 
349  
350 
351 var categories =
352 
353    from p in db.Products
354 
355   group p by new { Criterion = p.UnitPrice > 10 } into g
356 
357   select g;
358 
359  
360 
361 語句描述:使用Group By返回兩個產品序列。第一個序列包含單價大於10的產品。第二個序列包含單價小於或等於10的產品。
362 
363  
364 
365 說明:按產品單價是否大於10分類。其結果分為兩類,大於的是一類,小於及等於為另一類。
Group By/Having 分組查詢

 

LINQ to SQL語句(7)之Exists/In/Any/All/Contains

Exists/In/Any/All/Contains操作符

 

適用場景:用於判斷集合中元素,進一步縮小范圍。

 

 

  1 Any
  2 
  3  
  4 
  5 說明:用於判斷集合中是否有元素滿足某一條件;不延遲。(若條件為空,則集合只要不為空就返回True,否則為 False)。有2種形式,分別為簡單形式和帶條件形式。
  6 
  7  
  8 
  9 1.簡單形式:
 10 
 11  
 12 
 13 僅返回沒有訂單的客戶:
 14 
 15  
 16 
 17 var q =
 18 
 19   from c in db.Customers
 20 
 21   where !c.Orders.Any()
 22 
 23   select c;
 24 
 25  
 26 
 27 生成SQL語句為:
 28 
 29  
 30 
 31 SELECT [t0].[CustomerID],[t0].[CompanyName], [t0].[ContactName],
 32 
 33 [t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region],
 34 
 35 [t0].[PostalCode], [t0].[Country],[t0].[Phone], [t0].[Fax]
 36 
 37 FROM [dbo].[Customers] AS [t0]
 38 
 39 WHERE NOT (EXISTS(
 40 
 41   SELECT NULL AS [EMPTY] FROM [dbo].[Orders] AS [t1]
 42 
 43   WHERE [t1].[CustomerID] = [t0]. [CustomerID]
 44 
 45   ))
 46 
 47  
 48 
 49 2.帶條件形式:
 50 
 51  
 52 
 53 僅返回至少有一種產品斷貨的類別:
 54 
 55  
 56 
 57 var q =
 58 
 59   from c in db.Categories
 60 
 61   where c.Products.Any(p => p.Discontinued)
 62 
 63   select c;
 64 
 65  
 66 
 67 生成SQL語句為:
 68 
 69  
 70 
 71 SELECT [t0]. [CategoryID],[t0].[CategoryName], [t0].[Description],
 72 
 73 [t0]. [Picture] FROM [dbo].[Categories] AS[t0]
 74 
 75 WHERE EXISTS(
 76 
 77    SELECT NULL AS [EMPTY] FROM [dbo].[Products] AS [t1]
 78 
 79   WHERE ([t1].[Discontinued] = 1) AND
 80 
 81   ([t1].[CategoryID] = [t0]. [CategoryID])
 82 
 83   )
 84 
 85 All
 86 
 87 說明:用於判斷集合中所有元素是否都滿足某一條件;不延遲1.帶條件形式
 88 
 89  
 90 
 91 var q =
 92 
 93   from c in db.Customers
 94 
 95   where c.Orders.All(o => o.ShipCity == c.City)
 96 
 97   select c;
 98 
 99  
100 
101 語句描述:這個例子返回所有訂單都運往其所在城市的客戶或未下訂單的客戶。
102 
103  
104 
105 Contains
106 
107  
108 
109 說明:用於判斷集合中是否包含有某一元素;不延遲。它是對兩個序列進行連接操作的。
110 
111  
112 
113 string[] customerID_Set =
114 
115   new string[] { "AROUT", "BOLID","FISSA" };
116 
117 var q = (
118 
119   from o in db.Orders
120 
121   where customerID_Set.Contains(o.CustomerID)
122 
123   select o).ToList ();
124 
125  
126 
127 語句描述:查找"AROUT", "BOLID""FISSA" 這三個客戶的訂單。先定義了一個數組,在LINQ to SQL中使用Contains,數組中包含了所有的CustomerID,即返回結果中,所有的 CustomerID都在這個集合內。也就是in。你也可以把數組的定義放在LINQ to SQL語句里。比如:
128 
129  
130 
131 var q = (
132 
133   from o in db.Orders
134 
135   where (
136 
137   new string[] { "AROUT", "BOLID","FISSA" })
138 
139   .Contains (o.CustomerID)
140 
141   select o).ToList();
142 
143 Not Contains則取反:
144 
145 var q = (
146 
147   from o in db.Orders
148 
149   where !(
150 
151   new string[] { "AROUT", "BOLID","FISSA" })
152 
153   .Contains(o.CustomerID)
154 
155   select o).ToList();
156 
157  
158 
159 1.包含一個對象:
160 
161  
162 
163 var order = (from o in db.Orders
164 
165        where o.OrderID == 10248
166 
167        select o).First();
168 
169 var q = db.Customers.Where(p =>p.Orders.Contains(order)).ToList();
170 
171 foreach (var cust in q)
172 
173 {
174 
175   foreach (var ord in cust.Orders)
176 
177   {
178 
179     //do something
180 
181   }
182 
183 }
184 
185  
186 
187 語句描述:這個例子使用Contain查找哪個客戶包含OrderID為10248的訂單。
188 
189  
190 
191 2.包含多個值:
192 
193  
194 
195 string[] cities =
196 
197   new string[] { "Seattle", "London","Vancouver", "Paris" };
198 
199 var q = db.Customers.Where(p=>cities.Contains(p.City)).ToList();
200 
201  
202 
203 語句描述:這個例子使用Contains查找其所在城市為西雅圖、倫敦、巴黎或溫哥華的客戶
Exists/In/Any/All/Contains

LINQ to SQL語句(8)之Concat/Union/Intersect/Except

Concat/Union/Intersect/Except操作

 

適用場景:對兩個集合的處理,例如追加、合並、取相同項、相交項等等。

 

  1 Concat(連接)
  2 
  3  
  4 
  5 說明:連接不同的集合,不會自動過濾相同項;延遲。
  6 
  7  
  8 
  9 1.簡單形式:
 10 
 11 var q = (
 12 
 13      from c in db.Customers
 14 
 15      select c.Phone
 16 
 17     ).Concat(
 18 
 19      from c in db.Customers
 20 
 21      select c.Fax
 22 
 23     ).Concat(
 24 
 25      from e in db.Employees
 26 
 27      select e.HomePhone
 28 
 29     );
 30 
 31  
 32 
 33 語句描述:返回所有消費者和雇員的電話和傳真。
 34 
 35  
 36 
 37 2.復合形式:
 38 
 39 var q = (
 40 
 41      from c in db.Customers
 42 
 43      select new
 44 
 45      {
 46 
 47        Name = c.CompanyName,
 48 
 49        c.Phone
 50 
 51      }
 52 
 53      ).Concat(
 54 
 55      from e in db.Employees
 56 
 57      select new
 58 
 59      {
 60 
 61        Name = e.FirstName + " " + e.LastName,
 62 
 63        Phone = e.HomePhone
 64 
 65      }
 66 
 67     );
 68 
 69  
 70 
 71 語句描述:返回所有消費者和雇員的姓名和電話。
 72 
 73  
 74 
 75 Union(合並)
 76 
 77  
 78 
 79 說明:連接不同的集合,自動過濾相同項;延遲。即是將兩個集合進行合並操作,過濾相同的項。
 80 
 81  
 82 
 83 var q = (
 84 
 85      from c in db.Customers
 86 
 87      select c.Country
 88 
 89     ).Union(
 90 
 91      from e in db.Employees
 92 
 93      select e.Country
 94 
 95     );
 96 
 97  
 98 
 99 語句描述:查詢顧客和職員所在的國家。
100 
101  
102 
103 Intersect(相交)
104 
105  
106 
107 說明:取相交項;延遲。即是獲取不同集合的相同項(交集)。即先遍歷第一個集合,找出所有唯一的元素,然后遍歷第二個集合,並將每個元素與前面找出的元素作對比,返回所有在兩個集合內都出現的元素。
108 
109  
110 
111 var q = (
112 
113      from c in db.Customers
114 
115      select c.Country
116 
117     ).Intersect (
118 
119      from e in db.Employees
120 
121      select e.Country
122 
123     );
124 
125  
126 
127 語句描述:查詢顧客和職員同在的國家。
128 
129  
130 
131 Except(與非)
132 
133  
134 
135 說明:排除相交項;延遲。即是從某集合中刪除與另一個集合中相同的項。先遍歷第一個集合,找出所有唯一的元素,然后再遍歷第二個集合,返回第二個集合中所有未出現在前面所得元素集合中的元素。
136 
137  
138 
139 var q = (
140 
141      from c in db.Customers
142 
143      select c.Country
144 
145     ).Except(
146 
147      from e in db.Employees
148 
149      select e.Country
150 
151     );
152 
153  
154 
155 語句描述:查詢顧客和職員不同的國家。
Concat/Union/Intersect/Except

 

 

 

LINQ to SQL語句(9)之Top/Bottom和Paging分頁和SqlMethods

Top/Bottom操作(Take,Skip)

 

 

 

適用場景:適量的取出自己想要的數據,不是全部取出,這樣性能有所加強。

 

  1 Take
  2 
  3  
  4 
  5 說明:獲取集合的前n個元素;延遲。即只返回限定數量的結果集。
  6 
  7  
  8 
  9 var q = (
 10 
 11   from e in db.Employees
 12 
 13   orderby e.HireDate
 14 
 15   select e)
 16 
 17   .Take(5);
 18 
 19  
 20 
 21 語句描述:選擇所雇用的前5個雇員。
 22 
 23  
 24 
 25 Skip
 26 
 27  
 28 
 29 說明:跳過集合的前n個元素;延遲。即我們跳過給定的數目返回后面的結果集。
 30 
 31  
 32 
 33 var q = (
 34 
 35   from p in db.Products
 36 
 37   orderby p.UnitPrice descending
 38 
 39   select p)
 40 
 41   .Skip (10);
 42 
 43  
 44 
 45 語句描述:選擇10種最貴產品之外的所有產品。
 46 
 47  
 48 
 49 TakeWhile
 50 
 51  
 52 
 53 說明:直到某一條件成立就停止獲取;延遲。即用其條件去依次判斷源序列中的元素,返回符合判斷條件的元素,該判斷操作將在返回 false或源序列的末尾結束。
 54 
 55  
 56 
 57 SkipWhile
 58 
 59  
 60 
 61 說明:直到某一條件成立就停止跳過;延遲。即用其條件去判斷源序列中的元素並且跳過第一個符合判斷條件的元素,一旦判斷返回false,接下來將不再進行判斷並返回剩下的所有元素。
 62 
 63  
 64 
 65 Paging(分頁)操作
 66 
 67  
 68 
 69 適用場景:結合Skip和Take就可實現對數據分頁操作。
 70 
 71  
 72 
 73 1.索引
 74 
 75 var q = (
 76 
 77   from c in db.Customers
 78 
 79   orderby c.ContactName
 80 
 81   select c)
 82 
 83   .Skip(50)
 84 
 85   .Take(10);
 86 
 87  
 88 
 89 語句描述:使用Skip和Take運算符進行分頁,跳過前50條記錄,然后返回接下來10條記錄,因此提供顯示 Products表第6頁的數據。
 90 
 91  
 92 
 93 2.按唯一鍵排序
 94 
 95 var q = (
 96 
 97    from p in db.Products
 98 
 99   where p.ProductID > 50
100 
101    orderby p.ProductID
102 
103   select p)
104 
105   .Take(10);
106 
107  
108 
109 語句描述:使用Where子句和Take運算符進行分頁,首先篩選得到僅50 (第5頁最后一個ProductID)以上的ProductID,然后按ProductID排序,最后取前10個結果,因此提供Products表第6頁的數據。請注意,此方法僅適用於按唯一鍵排序的情況。
110 
111  
112 
113 SqlMethods操作
114 
115  
116 
117 在LINQ to SQL語句中,為我們提供了 SqlMethods操作,進一步為我們提供了方便,例如Like方法用於自定義通配表達式,Equals用於相比較是否相等。
118 
119  
120 
121 Like
122 
123  
124 
125 自定義的通配表達式。%表示零長度或任意長度的字符串;_表示一個字符;[]表示在某范圍區間的一個字符;[^]表示不在某范圍區間的一個字符。比如查詢消費者ID以“C”開頭的消費者。
126 
127  
128 
129 var q = from c in db.Customers
130 
131      where SqlMethods.Like(c.CustomerID, "C%")
132 
133      select c;
134 
135  
136 
137 比如查詢消費者ID沒有“AXOXT”形式的消費者:
138 
139  
140 
141 var q = from c in db.Customers
142 
143     where ! SqlMethods.Like(c.CustomerID, "A_O_T")
144 
145     select c;
146 
147 DateDiffDay
148 
149  
150 
151 說明:在兩個變量之間比較。分別有:DateDiffDay、 DateDiffHour、DateDiffMillisecond、DateDiffMinute、DateDiffMonth、 DateDiffSecond、DateDiffYear 
152 
153  
154 
155 var q = from o in db.Orders
156 
157     where SqlMethods
158 
159     .DateDiffDay (o.OrderDate, o.ShippedDate) < 10
160 
161     select o;
162 
163  
164 
165 語句描述:查詢在創建訂單后的 10 天內已發貨的所有訂單。
166 
167  
168 
169 已編譯查詢操作(Compiled Query)
170 
171  
172 
173 說明:在之前我們沒有好的方法對寫出的SQL語句進行編輯重新查詢,現在我們可以這樣做,看下面一個例子:
174 
175  
176 
177 //1. 創建compiled query
178 
179 NorthwindDataContext db = newNorthwindDataContext();
180 
181 var fn = CompiledQuery.Compile(
182 
183    (NorthwindDataContext db2, string city) =>
184 
185   from c in db2.Customers
186 
187   where c.City == city
188 
189   select c);
190 
191 //2.查詢城市為London的消費者,用LonCusts集合表示,這時可以用數據控件 綁定
192 
193 var LonCusts = fn(db, "London");
194 
195 //3.查詢城市 為Seattle的消費者
196 
197 var SeaCusts = fn(db, "Seattle");
198 
199  
200 
201 語句描述:這個例子創建一個已編譯查詢,然后使用它檢索輸入城市的客戶。
條件查詢

 

LINQ to SQL語句(10)之Insert

插入(Insert)

 

  1 1.簡單形式
  2 
  3 說明:new一個對象,使用InsertOnSubmit方法將其加入到對應的集合中,使用SubmitChanges()提交到數據庫。
  4 
  5  
  6 
  7 NorthwindDataContext db = newNorthwindDataContext();
  8 
  9 var newCustomer = new Customer
 10 
 11 {
 12 
 13   CustomerID = "MCSFT",
 14 
 15   CompanyName = "Microsoft",
 16 
 17   ContactName = "John Doe",
 18 
 19   ContactTitle = "Sales Manager",
 20 
 21   Address = "1 Microsoft Way",
 22 
 23   City = "Redmond",
 24 
 25   Region = "WA",
 26 
 27   PostalCode = "98052",
 28 
 29    Country = "USA",
 30 
 31   Phone = "(425) 555- 1234",
 32 
 33   Fax = null
 34 
 35 };
 36 
 37 db.Customers.InsertOnSubmit(newCustomer);
 38 
 39 db.SubmitChanges ();
 40 
 41  
 42 
 43 語句描述:使用InsertOnSubmit方法將新客戶添加到Customers 表對象。調用SubmitChanges 將此新Customer保存到數據庫。
 44 
 45  
 46 
 47 2.一對多關系
 48 
 49  
 50 
 51 說明:Category與Product是一對多的關系,提交Category(一端)的數據時,LINQ to SQL會自動將Product(多端)的數據一起提交。
 52 
 53  
 54 
 55 var newCategory = new Category
 56 
 57 {
 58 
 59   CategoryName = "Widgets",
 60 
 61   Description = "Widgets are the ……"
 62 
 63 };
 64 
 65 var newProduct = new Product
 66 
 67 {
 68 
 69   ProductName = "Blue Widget",
 70 
 71   UnitPrice = 34.56M,
 72 
 73   Category = newCategory
 74 
 75 };
 76 
 77 db.Categories.InsertOnSubmit(newCategory);
 78 
 79 db.SubmitChanges ();
 80 
 81  
 82 
 83 語句描述:使用InsertOnSubmit方法將新類別添加到Categories 表中,並將新Product對象添加到與此新Category有外鍵關系的Products表中。調用SubmitChanges將這些新對象及其關系保存到數據庫。
 84 
 85  
 86 
 87 3.多對多關系
 88 
 89  
 90 
 91 說明:在多對多關系中,我們需要依次提交。
 92 
 93  
 94 
 95 var newEmployee = new Employee
 96 
 97 {
 98 
 99   FirstName = "Kira",
100 
101   LastName = "Smith"
102 
103 };
104 
105 var newTerritory = new Territory
106 
107 {
108 
109   TerritoryID = "12345",
110 
111   TerritoryDescription = "Anytown",
112 
113   Region = db.Regions.First()
114 
115 };
116 
117 var newEmployeeTerritory = newEmployeeTerritory
118 
119 {
120 
121    Employee = newEmployee,
122 
123   Territory = newTerritory
124 
125 };
126 
127 db.Employees.InsertOnSubmit(newEmployee);
128 
129 db.Territories.InsertOnSubmit(newTerritory);
130 
131 db.EmployeeTerritories.InsertOnSubmit(newEmployeeTerritory);
132 
133 db.SubmitChanges();
134 
135  
136 
137 語句描述:使用InsertOnSubmit方法將新雇員添加到Employees 表中,將新Territory添加到Territories表中,並將新 EmployeeTerritory對象添加到與此新Employee對象和新Territory對象有外鍵關系的EmployeeTerritories表中。調用SubmitChanges將這些新對象及其關系保持到數據庫。
138 
139  
140 
141 4.使用動態CUD重寫(Overrideusing Dynamic CUD)
142 
143  
144 
145 說明:CUD就是Create、Update、Delete的縮寫。下面的例子就是新建一個ID(主鍵) 為32的Region,不考慮數據庫中有沒有ID為32的數據,如果有則替換原來的數據,沒有則插入。
146 
147  
148 
149 Region nwRegion = new Region()
150 
151 {
152 
153   RegionID = 32,
154 
155   RegionDescription = "Rainy"
156 
157 };
158 
159 db.Regions.InsertOnSubmit(nwRegion);
160 
161 db.SubmitChanges ();
162 
163  
164 
165 語句描述:使用DataContext提供的分部方法InsertRegion插入一個區域。對SubmitChanges 的調用調用InsertRegion 重寫,后者使用動態CUD運行Linq To SQL生成的默認SQL查詢。
Insert 插入

 

LINQ to SQL語句(11)之Update

更新(Update)

 

說明:更新操作,先獲取對象,進行修改操作之后,直接調用SubmitChanges()方法即可提交。注意,這里是在同一個DataContext中,對於不同的DataContex看下面的講解。

 

 1 1.簡單形式
 2 
 3 Customer cust =
 4 
 5   db.Customers.First(c => c.CustomerID == "ALFKI");
 6 
 7 cust.ContactTitle = "VicePresident";
 8 
 9 db.SubmitChanges();
10 
11  
12 
13 語句描述:使用 SubmitChanges將對檢索到的一個Customer對象做出的更新保持回數據庫。
14 
15  
16 
17 2.多項更改
18 
19 var q = from p in db.Products
20 
21      where p.CategoryID == 1
22 
23     select p;
24 
25 foreach (var p in q)
26 
27 {
28 
29   p.UnitPrice += 1.00M;
30 
31 }
32 
33 db.SubmitChanges ();
34 
35  
36 
37 語句描述:使用SubmitChanges將對檢索到的進行的更新保持回數據庫。
更新(Update)

 

LINQ to SQL語句(12)之Delete和使用Attach

刪除(Delete)

 

  1 1.簡單形式
  2 
  3  
  4 
  5 說明:調用DeleteOnSubmit方法即可。
  6 
  7  
  8 
  9 OrderDetail orderDetail =
 10 
 11    db.OrderDetails.First
 12 
 13   (c => c.OrderID == 10255 && c.ProductID == 36);
 14 
 15 db.OrderDetails.DeleteOnSubmit(orderDetail);
 16 
 17 db.SubmitChanges();
 18 
 19  
 20 
 21 語句描述:使用 DeleteOnSubmit方法從OrderDetail 表中刪除OrderDetail對象。調用 SubmitChanges 將此刪除保持到數據庫。
 22 
 23  
 24 
 25 2.一對多關系
 26 
 27  
 28 
 29 說明:Order 與OrderDetail是一對多關系,首先DeleteOnSubmit其OrderDetail(多端),其次 DeleteOnSubmit其Order(一端)。因為一端是主鍵。
 30 
 31  
 32 
 33 var orderDetails =
 34 
 35   from o in db.OrderDetails
 36 
 37   where o.Order.CustomerID == "WARTH" &&
 38 
 39    o.Order.EmployeeID == 3
 40 
 41   select o;
 42 
 43 var order =
 44 
 45    (from o in db.Orders
 46 
 47    where o.CustomerID == "WARTH" && o.EmployeeID ==3
 48 
 49    select o).First();
 50 
 51 foreach (OrderDetail od in orderDetails)
 52 
 53 {
 54 
 55    db.OrderDetails.DeleteOnSubmit(od);
 56 
 57 }
 58 
 59 db.Orders.DeleteOnSubmit(order);
 60 
 61 db.SubmitChanges();
 62 
 63  
 64 
 65 語句描述語句描述:使用DeleteOnSubmit方法從Order 和Order Details表中刪除Order和Order Detail對象。首先從Order Details刪除,然后從Orders刪除。調用SubmitChanges將此刪除保持到數據庫。
 66 
 67  
 68 
 69 3.推理刪除(Inferred Delete)
 70 
 71  
 72 
 73 說明:Order與OrderDetail是一對多關系,在上面的例子,我們全部刪除CustomerID為WARTH和EmployeeID為3 的數據,那么我們不須全部刪除呢?例如Order的OrderID為10248的OrderDetail有很多,但是我們只要刪除 ProductID為11的OrderDetail。這時就用Remove方法。
 74 
 75  
 76 
 77 Order order = db.Orders.First(x =>x.OrderID == 10248);
 78 
 79 OrderDetail od =
 80 
 81   order.OrderDetails.First(d => d.ProductID == 11);
 82 
 83 order.OrderDetails.Remove(od);
 84 
 85 db.SubmitChanges();
 86 
 87  
 88 
 89 語句描述語句描述:這個例子說明在實體對象的引用實體將該對象從其EntitySet 中移除時,推理刪除如何導致在該對象上發生實際的刪除操作。僅當實體的關聯映射將DeleteOnNull設置為true且CanBeNull 為false 時,才會發生推理刪除行為。
 90 
 91  
 92 
 93 使用Attach更新(Updatewith Attach)
 94 
 95  
 96 
 97 說明:在對於在不同的 DataContext之間,使用Attach方法來更新數據。例如在一個名為tempdb的 NorthwindDataContext中,查詢出Customer和Order,在另一個 NorthwindDataContext中,Customer的地址更新為123 First Ave,Order的 CustomerID 更新為CHOPS。
 98 
 99  
100 
101 //通常,通過從其他層反序列化 XML 來獲取要附加的實體
102 
103 //不支持將實體從一個DataContext附加到另一個DataContext
104 
105 //因此若要復制反序列化實體的操作,將在此處重新創建這 些實體
106 
107 Customer c1;
108 
109 List<Order> deserializedOrders = newList<Order>();
110 
111 Customer deserializedC1;
112 
113 using (NorthwindDataContext tempdb = newNorthwindDataContext())
114 
115 {
116 
117   c1 = tempdb.Customers.Single(c => c.CustomerID =="ALFKI");
118 
119   deserializedC1 = new Customer
120 
121    {
122 
123     Address = c1.Address,
124 
125     City = c1.City,
126 
127     CompanyName = c1.CompanyName,
128 
129     ContactName = c1.ContactName,
130 
131     ContactTitle = c1.ContactTitle,
132 
133     Country = c1.Country,
134 
135     CustomerID = c1.CustomerID,
136 
137     Fax = c1.Fax,
138 
139     Phone = c1.Phone,
140 
141      PostalCode = c1.PostalCode,
142 
143     Region = c1.Region
144 
145   };
146 
147   Customer tempcust =
148 
149      tempdb.Customers.Single(c => c.CustomerID == "ANTON");
150 
151   foreach (Order o in tempcust.Orders)
152 
153   {
154 
155      deserializedOrders.Add(new Order
156 
157     {
158 
159        CustomerID = o.CustomerID,
160 
161       EmployeeID = o.EmployeeID,
162 
163       Freight = o.Freight,
164 
165        OrderDate = o.OrderDate,
166 
167       OrderID = o.OrderID,
168 
169       RequiredDate = o.RequiredDate,
170 
171       ShipAddress = o.ShipAddress,
172 
173       ShipCity = o.ShipCity,
174 
175       ShipName = o.ShipName,
176 
177       ShipCountry = o.ShipCountry,
178 
179       ShippedDate = o.ShippedDate,
180 
181       ShipPostalCode = o.ShipPostalCode,
182 
183       ShipRegion = o.ShipRegion,
184 
185       ShipVia = o.ShipVia
186 
187     });
188 
189   }
190 
191 }
192 
193 using (NorthwindDataContext db2 = newNorthwindDataContext())
194 
195 {
196 
197   //將第一個實體附加到當前數據上下文,以跟蹤更改
198 
199   //對Customer更新,不能寫錯
200 
201    db2.Customers.Attach(deserializedC1);
202 
203   //更改所跟蹤的實體
204 
205   deserializedC1.Address = "123 First Ave";
206 
207   // 附加訂單列表中的所有實體
208 
209   db2.Orders.AttachAll (deserializedOrders);
210 
211   //將訂單更新為屬於其他客戶
212 
213    foreach (Order o in deserializedOrders)
214 
215   {
216 
217      o.CustomerID = "CHOPS";
218 
219   }
220 
221   //在當前數據上下文中提交更改
222 
223   db2.SubmitChanges();
224 
225 }
226 
227  
228 
229 語句描述:從另一個層中獲取實體,使用Attach和AttachAll將反序列化后的實體附加到數據上下文,然后更新實體。更改被提交到數據庫。
230 
231  
232 
233 使用Attach更新和刪除(Update and Delete with Attach)
234 
235  
236 
237 說明:在不同的DataContext中,實現插入、更新、刪除。看下面的一個例子:
238 
239  
240 
241 //通常,通過從其他層 反序列化XML獲取要附加的實體
242 
243 //此示例使用 LoadWith 在一個查詢中預 先加載客戶和訂單,
244 
245 //並禁用延遲加載
246 
247 Customer cust = null;
248 
249 using (NorthwindDataContext tempdb = newNorthwindDataContext())
250 
251 {
252 
253   DataLoadOptions shape = new DataLoadOptions();
254 
255    shape.LoadWith<Customer>(c => c.Orders);
256 
257   //加載第一個客戶實體及其訂單
258 
259   tempdb.LoadOptions = shape;
260 
261    tempdb.DeferredLoadingEnabled = false;
262 
263   cust = tempdb.Customers.First(x => x.CustomerID =="ALFKI");
264 
265 }
266 
267 Order orderA = cust.Orders.First();
268 
269 Order orderB = cust.Orders.First(x =>x.OrderID > orderA.OrderID);
270 
271 using (NorthwindDataContext db2 = newNorthwindDataContext())
272 
273 {
274 
275   //將第一個實體附加到當前數據上下文,以跟蹤更改
276 
277    db2.Customers.Attach(cust);
278 
279   //附加相關訂單以進行跟蹤; 否則將在提交時插入它們
280 
281   db2.Orders.AttachAll(cust.Orders.ToList ());
282 
283   //更新客戶的Phone.
284 
285   cust.Phone = "2345 5436";
286 
287   //更新第一個訂單OrderA的ShipCity.
288 
289    orderA.ShipCity = "Redmond";
290 
291   //移除第二個訂單 OrderB.
292 
293   cust.Orders.Remove(orderB);
294 
295   //添加一個新的訂單Order到客戶Customer中.
296 
297   Order orderC = new Order() { ShipCity = "New York" };
298 
299   cust.Orders.Add (orderC);
300 
301   //提交執行
302 
303   db2.SubmitChanges();
304 
305 }
306 
307  
308 
309 語句描述:從一個上下文提取實體,並使用 Attach 和 AttachAll 附加來自其他上下文的實體,然后更新這兩個實體,刪除一個實體,添加另一個實體。更改被提交到數據庫。
Delete 刪除

 

LINQ to SQL語句(13)之開放式並發控制和事務

Simultaneous Changes開放式並發控制

下表介紹 LINQ to SQL 文檔中涉及開放式並發的術語

 

 1 並發兩個或更多用戶同時嘗試更新同一數據庫行的情形。
 2 
 3 並發沖突兩個或更多用戶同時嘗試向一行的一列或多列提交沖突值的情形。
 4 
 5 並發控制用於解決並發沖突的技術。
 6 
 7 開放式並發控制先調查其他事務是否已更改了行中的值,再允許提交更改的技術。相比之下,保守式並發控制則是通過鎖定記錄來避免發生並發沖突。之所以稱作開放式控制,是因為它將一個事務干擾另一事務視為不太可能發生。
 8 
 9 沖突解決通過重新查詢數據庫刷新出現沖突的項,然后協調差異的過程。刷新對象時,LINQ to SQL 更改跟蹤器會保留以下數據:最初從數據庫獲取並用於更新檢查的值通過后續查詢獲得的新數據庫值。 LINQ to SQL 隨后會確定相應對象是否發生沖突(即它的一個或多個成員值是否已發生更改)。如果此對象發生沖突,LINQ to SQL 下一步會確定它的哪些成員發生沖突。LINQ to SQL 發現的任何成員沖突都會添加到沖突列表中。
10 
11  
12 
13  
14 
15 在 LINQ to SQL 對象模型中,當以下兩個條件都得到滿足時,就會發生“開放式並發沖突”:客戶端嘗試向數據庫提交更改;數據庫中的一個或多個更新檢查值自客戶端上次讀取它們以來已得到更新。此沖突的解決過程包括查明對象的哪些成員發生沖突,然后決定您希望如何進行處理。
術語說明

 

開放式並發(Optimistic Concurrency)

 

 

說明:這個例子中在你讀取數據之前,另外一個用戶已經修改並提交更新了這個數據,所以不會出現沖突。

 

 1 //我們打開一個新的連接來模擬另外一個用戶
 2 
 3 NorthwindDataContext otherUser_db = newNorthwindDataContext();
 4 
 5 var otherUser_product =
 6 
 7   otherUser_db.Products.First(p => p.ProductID == 1);
 8 
 9 otherUser_product.UnitPrice = 999.99M;
10 
11 otherUser_db.SubmitChanges();
12 
13 //我們當前連接
14 
15 var product = db.Products.First(p =>p.ProductID == 1);
16 
17 product.UnitPrice = 777.77M;
18 
19 try
20 
21 {
22 
23   db.SubmitChanges();//當前連接執行成功
24 
25 }
26 
27 catch (ChangeConflictException)
28 
29 {
30 
31 }
32 
33  
34 
35 說明:我們讀取數據之后,另外一個用戶獲取並提交更新了這個數據,這時,我們更新這個數據時,引起了一個並發沖突。系統發生回滾,允許你可以從數據庫檢索新更新的數據,並決定如何繼續進行您自己的更新。
36 
37  
38 
39 //當前 用戶
40 
41 var product = db.Products.First(p =>p.ProductID == 1);
42 
43 //我們打開一個新的連接來模擬另外一個用戶
44 
45 NorthwindDataContext otherUser_db = newNorthwindDataContext() ;
46 
47 var otherUser_product =
48 
49   otherUser_db.Products.First(p => p.ProductID == 1);
50 
51 otherUser_product.UnitPrice = 999.99M;
52 
53 otherUser_db.SubmitChanges();
54 
55 //當前用戶修改
56 
57 product.UnitPrice = 777.77M;
58 
59 try
60 
61 {
62 
63    db.SubmitChanges();
64 
65 }
66 
67 catch (ChangeConflictException)
68 
69 {
70 
71   //發生異常!
72 
73 }
開放式並發

 

Transactions事務

LINQto SQL 支持三種事務模型,分別是:

 1 顯式本地事務:調用 SubmitChanges 時,如果 Transaction 屬性設置為事務,則在同一事務的上下文中執行 SubmitChanges 調用。成功執行事務后,要由您來提交或回滾事務。與事務對應的連接必須與用於構造 DataContext 的連接匹配。如果使用其他連接,則會引發異常。
 2 
 3  
 4 
 5 顯式可分發事務:可以在當前 Transaction 的作用域中調用 LINQ to SQL API(包括但不限於 SubmitChanges)。LINQ to SQL 檢測到調用是在事務的作用域內,因而不會創建新的事務。在這種情況下, <token>vbtecdlinq</token> 還會避免關閉連接。您可以在此類事 務的上下文中執行查詢和SubmitChanges 操作。
 6 
 7  
 8 
 9 隱式事務:當您調用 SubmitChanges 時,LINQ to SQL 會檢查此調用是否在 Transaction 的作用域內或者 Transaction 屬性是否設置為由用戶啟動的本地事務。如果這兩個事務它均未找到,則 LINQ to SQL 啟動本地事務,並使用此事務執行所生成的 SQL 命令。當所有 SQL 命令均已成功執行完畢時,LINQ to SQL 提交本地事務並返回。
10 
11  
12 
13 1.Implicit(隱式)
14 
15  
16 
17 說明:這個例子在執行SubmitChanges ()操作時,隱式地使用了事務。因為在更新2種產品的庫存數量時,第二個產品庫存數量為負數了,違反了服務器上的 CHECK 約束。這導致了更新產品全部失敗了,系統回滾到這個操作的初始狀態。
18 
19 try
20 
21 {
22 
23   Product prod1 = db.Products.First(p => p.ProductID == 4);
24 
25   Product prod2 = db.Products.First(p => p.ProductID == 5);
26 
27    prod1.UnitsInStock -= 3;
28 
29   prod2.UnitsInStock -= 5;//錯誤:庫存 數量的單位不能是負數
30 
31   //要么全部成功要么全部失敗
32 
33    db.SubmitChanges();
34 
35 }
36 
37 catch (System.Data.SqlClient.SqlExceptione)
38 
39 {
40 
41   //執行異常處理
42 
43 }
44 
45  
46 
47 2.Explicit(顯式)
48 
49  
50 
51 說明:這個例子使用顯式事務。通過在事務中加入對數據的讀取以防止出現開放式並發異常,顯式事務可以提供更多的保護。如同上一個查詢中,更新 prod2 的 UnitsInStock 字段將使該字段為負值,而這違反了數據庫中的 CHECK 約束。這導致更新這兩個產品的事務失敗,此時將回滾所有更改。
52 
53  
54 
55 using (TransactionScope ts = new TransactionScope())
56 
57 {
58 
59   try
60 
61   {
62 
63      Product prod1 = db.Products.First(p => p.ProductID == 4);
64 
65     Product prod2 = db.Products.First(p => p.ProductID == 5);
66 
67     prod1.UnitsInStock -= 3;
68 
69     prod2.UnitsInStock -= 5;//錯誤:庫存數量的單位不能是負數
70 
71     db.SubmitChanges();
72 
73   }
74 
75   catch (System.Data.SqlClient.SqlException e)
76 
77   {
78 
79     //執行異常處理
80 
81   }
82 
83 }
事務

LINQ to SQL語句(14)之Null語義和DateTime

Null語義

 

說明:下面第一個例子說明查詢ReportsToEmployee為null的雇員。第二個例子使用Nullable<T>.HasValue查詢雇員,其結果與第一個例 子相同。在第三個例子中,使用Nullable<T>.Value來返回ReportsToEmployee不為null的雇員的ReportsTo的值。

 1 1.Null
 2 
 3  
 4 
 5 查找不隸屬於另一個雇員的所有雇員:
 6 
 7  
 8 
 9 var q =
10 
11   from e in db.Employees
12 
13   where e.ReportsToEmployee == null
14 
15    select e;
16 
17 2.Nullable<T>.HasValue
18 
19  
20 
21 查找不隸屬於另一個雇員的所有雇員:
22 
23  
24 
25 var q =
26 
27   from e in db.Employees
28 
29   where !e.ReportsTo.HasValue
30 
31   select e;
32 
33 3.Nullable<T>.Value
34 
35  
36 
37 返回前者的EmployeeID 編號。請注意 .Value 為可選:
38 
39  
40 
41 var q =
42 
43   from e in db.Employees
44 
45   where e.ReportsTo.HasValue
46 
47   select new
48 
49   {
50 
51     e.FirstName,
52 
53     e.LastName,
54 
55     ReportsTo = e.ReportsTo.Value
56 
57   };
Null

日期函數

 

LINQ to SQL支持以下 DateTime方法。但是,SQLServer和CLR的DateTime類型在范圍和計時周期精度上不同,如下表。

 

類型最小值 最大 值 計時周期

System.DateTime 0001 年 1 月 1 日 9999 年 12 月 31 日 100 毫微秒(0.0000001秒)

T-SQL DateTime 1753 年 1 月 1 日 9999 年 12 月 31 日 3.33… 毫秒(0.0033333 秒)

T-SQL SmallDateTime 1900 年 1 月 1 日 2079 年 6 月 6 日 1 分鍾(60 秒)

 

 

CLR DateTime 類型與SQL Server類型相比,前者范圍更 大、精度更高。因此來自SQLServer的數據用CLR類型表示時,絕不會損失量值或精度。但如果反過來的話,則范圍可能會減小,精度可能會降低;SQL Server 日期不存在TimeZone概念,而在CLR中支持這個功能。

 

我們在LINQ to SQL查詢使用以當地時間、UTC 或固定時間要自己執行轉換。

 

下面用三個實例說明一下。

 1 1.DateTime.Year
 2 
 3 var q =
 4 
 5   from o in db.Orders
 6 
 7   where o.OrderDate.Value.Year == 1997
 8 
 9    select o;
10 
11  
12 
13 語句描述:這個例子使用DateTime 的Year 屬性查找1997 年下的訂單。
1.DateTime.Year
 1 2.DateTime.Month
 2 
 3 var q =
 4 
 5   from o in db.Orders
 6 
 7   where o.OrderDate.Value.Month == 12
 8 
 9   select o;
10 
11  
12 
13 語句描述:這個例子使用DateTime的Month屬性查找十二月下的訂單。
2.DateTime.Month
 1 3.DateTime.Day
 2 
 3 var q =
 4 
 5   from o in db.Orders
 6 
 7   where o.OrderDate.Value.Day == 31
 8 
 9   select o;
10 
11  
12 
13 語句描述:這個例子使用DateTime的Day屬性查找某月 31 日下的訂單。
3.DateTime.Day

LINQ to SQL語句(15)之String

字符串(String)

 

LINQ to SQL支持以下String方法。但是不同的是默認 情況下System.String方法區分大小寫。而SQL則不區分大小寫。

 1 1.字符串串聯(StringConcatenation)
 2 
 3 var q =
 4 
 5   from c in db.Customers
 6 
 7   select new
 8 
 9   {
10 
11      c.CustomerID,
12 
13     Location = c.City + ", " + c.Country
14 
15   };
16 
17  
18 
19 語句描述:這個例子使用+運算符在形成經計算得出的客戶Location值過程中將字符串字段和字符串串聯在一起。
1.字符串串聯(StringConcatenation)
 1 2.String.Length
 2 
 3 var q =
 4 
 5   from p in db.Products
 6 
 7   where p.ProductName.Length < 10
 8 
 9   select p;
10 
11  
12 
13 語句描述:這個例子使用Length屬性查找名稱短於10個字符的所有產品。
2.String.Length
 1 3.String.Contains(substring)
 2 
 3 var q =
 4 
 5   from c in db.Customers
 6 
 7   where c.ContactName.Contains ("Anders")
 8 
 9   select c;
10 
11  
12 
13 語句描述:這個例子使用Contains方法查找所有其聯系人姓名中包含“Anders”的客戶。
3.String.Contains(substring)
 1 4.String.IndexOf(substring)
 2 
 3 var q =
 4 
 5   from c in db.Customers
 6 
 7   select new
 8 
 9   {
10 
11      c.ContactName,
12 
13     SpacePos = c.ContactName.IndexOf(" ")
14 
15   };
16 
17  
18 
19 語句描述:這個例子使用IndexOf方法查找每個客戶聯系人姓名中出現第一個空格的位置。
4.String.IndexOf(substring)
 1 5.String.StartsWith (prefix)
 2 
 3 var q =
 4 
 5   from c in db.Customers
 6 
 7   where c.ContactName.StartsWith("Maria")
 8 
 9   select c;
10 
11  
12 
13 語句描述:這個例子使用StartsWith方法查找聯系人姓名以“Maria”開頭的客戶。
5.String.StartsWith (prefix)
 1 6.String.EndsWith(suffix)
 2 
 3 var q =
 4 
 5   from c in db.Customers
 6 
 7   where c.ContactName.EndsWith("Anders")
 8 
 9   select c;
10 
11  
12 
13 語句描述:這個例子使用EndsWith方法查找聯系人姓名以“Anders”結尾的客戶。
6.String.EndsWith(suffix)
 1 7.String.Substring(start)
 2 
 3 var q =
 4 
 5   from p in db.Products
 6 
 7   select p.ProductName.Substring(3);
 8 
 9  
10 
11 語句描述:這個例子使用Substring方法返回產品名稱中從第四個字母開始的部分。
7.String.Substring(start)
 1 8.String.Substring (start, length)
 2 
 3 var q =
 4 
 5   from e in db.Employees
 6 
 7    where e.HomePhone.Substring(6, 3) == "555"
 8 
 9   select e;
10 
11  
12 
13 語句描述:這個例子使用Substring方法查找家庭電話號碼第七位到第九位是“555”的雇員。
8.String.Substring (start, length)
 1 9.String.ToUpper()
 2 
 3 var q =
 4 
 5   from e in db.Employees
 6 
 7   select new
 8 
 9   {
10 
11     LastName = e.LastName.ToUpper(),
12 
13     e.FirstName
14 
15   };
16 
17  
18 
19 語句描述:這個例子使用ToUpper方法返回姓氏已轉換為大寫的雇員姓名。
9.String.ToUpper()
 1 10.String.ToLower()
 2 
 3 var q =
 4 
 5   from c in db.Categories
 6 
 7   select c.CategoryName.ToLower();
 8 
 9  
10 
11 語句描述:這個例子使用ToLower方法返回已轉換為小寫的類別名稱。
10.String.ToLower()
 1 11.String.Trim()
 2 
 3 var q =
 4 
 5   from e in db.Employees
 6 
 7   select e.HomePhone.Substring(0, 5).Trim ();
 8 
 9  
10 
11 語句描述:這個例子使用Trim方法返回雇員家庭電話號碼的前五位,並移除前導和尾隨空格。
11.String.Trim()
 1 12.String.Insert(pos, str)
 2 
 3 var q =
 4 
 5   from e in db.Employees
 6 
 7   where e.HomePhone.Substring(4, 1) == ")"
 8 
 9   select e.HomePhone.Insert(5, ":");
10 
11  
12 
13 語句描述:這個例子使用 Insert方法返回第五位為 ) 的雇員電話號碼的序列,並在 ) 后面插入一個 :。
12.String.Insert(pos, str)
 1 13.String.Remove(start)
 2 
 3 var q =
 4 
 5   from e in db.Employees
 6 
 7   where e.HomePhone.Substring(4, 1) == ") "
 8 
 9   select e.HomePhone.Remove(9);
10 
11  
12 
13 語句描述:這個例子使用Remove方法返回第五位為 ) 的雇員電話號碼的序列,並移除從第十個字符開始的所有字符。
13.String.Remove(start)
 1 14.String.Remove(start, length)
 2 
 3 var q =
 4 
 5   from e in db.Employees
 6 
 7   where e.HomePhone.Substring(4, 1) == ")"
 8 
 9   select e.HomePhone.Remove(0, 6);
10 
11  
12 
13 語句描述:這個例子使用Remove方法返回第五位為 ) 的雇員電話號碼的序列,並移除前六個字符。
14.String.Remove(start, length)
 1 15.String.Replace(find, replace)
 2 
 3 var q =
 4 
 5   from s in db.Suppliers
 6 
 7   select new
 8 
 9   {
10 
11      s.CompanyName,
12 
13     Country = s.Country
14 
15     .Replace ("UK", "United Kingdom")
16 
17     .Replace ("USA", "United States of America")
18 
19   };
20 
21  
22 
23 語句描述:這個例子使用 Replace 方法返回 Country 字段中UK 被替換為 United Kingdom 以及USA 被替換為 United States of America 的供 應商信息
15.String.Replace(find, replace)

LINQ to SQL語句(16)之對象標識

 1 對象標識
 2 
 3  
 4 
 5 運行庫中的對象具有唯一標識。引用同一對象的兩個變量實際上是引用此對象的同一實例。你更改一個變量后,可以通過另一個變量看到這些更改。
 6 
 7  
 8 
 9 關系數據庫表中的行不具有唯一標識。由於每一行都具有唯一的主鍵,因此任何兩行都不會共用同一鍵值。
10 
11  
12 
13 實際上,通常我們是將數據從數據庫中提取出來放入另一層中,應用程序在該層對數據進行處理。這就是 LINQ to SQL 支持的模型。將數據作為行從數據庫中提取出來時,你不期望表示相同數據的兩行實際上對應於相同的行實例。如果您查詢特定客戶兩次,您將獲得兩行數據。每一行包含相同的信息。
14 
15  
16 
17 對於對象。你期望在你反復向 DataContext 索取相同的信息時,它實際上會為你提供同一對象實例。你將它們設計為層次結構或關系圖。你希望像檢索實物一樣檢索它們,而不希望僅僅因為你多次索要同一內容而收到大量的復制實例。
18 
19  
20 
21 在 LINQ to SQL 中, DataContext 管理對象標識。只要你從數據庫中檢索新行,該行就會由其主鍵記錄到標識表中,並且會創建一個新的對象。只要您檢索該行,就會將原始對象實例傳遞回應用程序。通過這種方式,DataContext 將數據庫看到的標識(即主鍵)的概念轉換成相應語言看到的標識(即實例)的概念。應用程序只看到處於第一次檢索時的狀態的對象。新數據如果不同,則會被丟棄。
22 
23  
24 
25 LINQ to SQL 使用此方法來管理本地對象的完整性,以支持開放式更新。由於在最初創建對象 后唯一發生的更改是由應用程序做出的,因此應用程序的意向是很明確的。如果在中間階段外部某一方做了更改,則在調用 SubmitChanges() 時會識別出這些更改。
26 
27  
28 
29 以上來自MSDN,的確,看了有點“正規”,下面我用兩個例子說明一下。
對象標識
 1 對象緩存
 2 
 3  
 4 
 5 在第一個示例中,如果我們執行同一查詢兩次,則每次都會收到對內存中同一對象的引用。很明顯,cust1和cust2是同一個對象引用。
 6 
 7  
 8 
 9 Customer cust1 = db.Customers.First(c =>c.CustomerID == "BONAP");
10 
11 Customer cust2 = db.Customers.First(c =>c.CustomerID == "BONAP");
12 
13  
14 
15 下面的示例中,如果您執行返回數據庫中同一行的不同查詢,則您每次都會收到對內存中同一對象的引用。cust1和cust2是同一個對象引用,但是數據庫查詢了兩次。
16 
17  
18 
19 Customer cust1 = db.Customers.First(c =>c.CustomerID == "BONAP");
20 
21 Customer cust2 = (
22 
23   from o in db.Orders
24 
25   where o.Customer.CustomerID == "BONAP"
26 
27   select o )
28 
29   .First()
30 
31   .Customer;
對象緩存

LINQ to SQL語句(17)之對象加載

 1 對象加載延遲加載
 2 
 3  
 4 
 5 在查詢某對象時,實際上你只查詢該對象。不會同時自動獲取這個對象。這就是延遲加載。
 6 
 7  
 8 
 9 例如,您可能需要查看客戶數據和訂單數據。你最初不一定需要檢索與每個客戶有關的所有訂單數據。其優點是你可以使用延遲加載將額外信息的檢索操作延遲到你確實需要檢索它們時再進行。請看下面的示例:檢索出來CustomerID,就根據這個ID查詢出OrderID。
10 
11  
12 
13 var custs =
14 
15    from c in db.Customers
16 
17    where c.City == "Sao Paulo"
18 
19    select c;
20 
21 //上面 的查詢句法不會導致語句立即執行,僅僅是一個描述性的語句,
22 
23 只有需要的時候才會執行它
24 
25 foreach (var cust in custs)
26 
27 {
28 
29    foreach (var ord in cust.Orders)
30 
31   {
32 
33     //同時查看客戶數據和訂單數據
34 
35   }
36 
37 }
38 
39  
40 
41 語句描述:原始查詢未請求數據,在所檢索到各個對象的鏈接中導航如何能導致觸發對數據庫的新查詢。
對象加載延遲加載
 1 預先加載:LoadWith 方法
 2 
 3  
 4 
 5 你如果想要同時查詢出一些對象的集合的方法。LINQ to SQL 提供了 DataLoadOptions用於立即加載對象。方法包括:
 6 
 7  
 8 
 9 LoadWith 方法,用於立即加載與主目標相關的數據。
10 
11  
12 
13 AssociateWith 方法,用於篩選為特定關系檢索到的對象。
14 
15  
16 
17 使用 LoadWith方法指定應同時檢索與主目標相關的哪些數據。例如,如果你知道你需要有關客戶的訂單的信息,則可以使用 LoadWith 來確保在檢索客戶信息的同時檢索訂單信息。使用此方法可僅訪問一次數據庫,但同時獲取兩組信息。
18 
19  
20 
21 在下面的示例中,我們通過設置DataLoadOptions,來指示DataContext 在加載Customers的同時把對應的Orders一起加載,在執行查詢時會檢索位於Sao Paulo的所有 Customers 的所有 Orders。這樣一來,連續訪問 Customer 對象的 Orders 屬性不會觸發新的數據庫查詢。在執行時生成的SQL語句使用了左連接。
22 
23  
24 
25 NorthwindDataContext db = newNorthwindDataContext ();
26 
27 DataLoadOptions ds = new DataLoadOptions();
28 
29 ds.LoadWith<Customer>(p =>p.Orders);
30 
31 db.LoadOptions = ds;
32 
33 var custs = (
34 
35    from c in db2.Customers
36 
37    where c.City == "Sao Paulo"
38 
39    select c);
40 
41 foreach (var cust in custs)
42 
43 {
44 
45   foreach (var ord in cust.Orders)
46 
47   {
48 
49     Console.WriteLine ("CustomerID {0} has an OrderID {1}.",
50 
51        cust.CustomerID,
52 
53       ord.OrderID);
54 
55   }
56 
57 }
58 
59  
60 
61 語句描述:在原始查詢過程中使用 LoadWith 請求相關數據,以便稍后在檢索到的各個對象中導航時不需要對數據庫進行額外的往返。
預先加載:LoadWith 方法

LINQ to SQL語句(18)之運算符轉換

 1 1.AsEnumerable:將類型轉換為泛型 IEnumerable
 2 
 3  
 4 
 5 使用 AsEnumerable<TSource> 可返回類型化為泛型 IEnumerable的參數。在 此示例中,LINQ toSQL(使用默認泛型 Query)會嘗試將查詢轉換為 SQL 並在服務器上執行。但 where 子句引用用戶定義的客戶端方法 (isValidProduct),此方法無法轉換為 SQL。
 6 
 7  
 8 
 9 解決方法是指定 where 的客戶端泛型 IEnumerable<T> 實現以替換泛型 IQueryable<T>。可通過調用 AsEnumerable<TSource>運算符來執行此操作。
10 
11  
12 
13 var q =
14 
15   from p in db.Products.AsEnumerable()
16 
17   where isValidProduct(p)
18 
19   select p;
20 
21  
22 
23 語句描述:這個例子就是使用AsEnumerable以便使用Where的客戶端IEnumerable實現,而不是默認的 IQueryable將在服務器上轉換為SQL並執行的默認Query<T>實現。這很有必要,因為Where子句引用了用戶定義的客戶端方法isValidProduct,該方法不能轉換為SQL。
1.AsEnumerable:將類型轉換為泛型 IEnumerable
 1 2.ToArray:將序列轉換為數組
 2 
 3  
 4 
 5 使用 ToArray <TSource>可從序列創建數組。
 6 
 7  
 8 
 9 var q =
10 
11   from c in db.Customers
12 
13   where c.City == "London"
14 
15    select c;
16 
17 Customer[] qArray = q.ToArray();
18 
19  
20 
21 語句描述:這個例子使用 ToArray 將查詢直接計算為數組。
2.ToArray:將序列轉換為數組
 1 3.ToList:將序列轉換為泛型列表
 2 
 3  
 4 
 5 使用 ToList<TSource>可從序列創建泛型列表。下面的示例使用 ToList<TSource>直接將查詢的計算結果放入泛型 List<T> 6 
 7  
 8 
 9 var q =
10 
11   from e in db.Employees
12 
13   where e.HireDate >= new DateTime(1994, 1, 1)
14 
15   select e;
16 
17 List<Employee> qList = q.ToList();
3.ToList:將序列轉換為泛型列表
 1 4.ToDictionary:將序列轉化為字典
 2 
 3  
 4 
 5 使用Enumerable.ToDictionary<TSource, TKey>方法可 以將序列轉化為字典。TSource表示source中的元素的類型;TKey表示keySelector返回的鍵的類型。其返回一個包含鍵和值的Dictionary<TKey, TValue> 6 
 7  
 8 
 9 var q =
10 
11   from p in db.Products
12 
13   where p.UnitsInStock <= p.ReorderLevel && ! p.Discontinued
14 
15   select p;
16 
17 Dictionary<int, Product> qDictionary=
18 
19   q.ToDictionary(p => p.ProductID);
20 
21 foreach (int key in qDictionary.Keys)
22 
23 {
24 
25    Console.WriteLine(key);
26 
27 }
28 
29  
30 
31 語句描述:這個例子使用 ToDictionary 將查詢和鍵表達式直接鍵表達式直接計算為 Dictionary<K, T>。
4.ToDictionary:將序列轉化為字典

LINQ to SQL語句(19)之ADO.NETLINQ to SQL

ADO.NET與LINQ to SQL

 

它基於由 ADO.NET 提供程序模型提供的服務。因此,我們可以將 LINQ to SQL 代碼與現有的 ADO.NET 應用程序混合在一起,將當前 ADO.NET 解決方案遷移到 LINQ to SQL。

 1 1.連接
 2 
 3  
 4 
 5 在創建 LINQ to SQL DataContext 時,可以提供現有 ADO.NET 連接。對DataContext 的所有操作(包括查詢)都使用所提供的這個連接。如果此連接已經打開,則在您使用完此連接時,LINQ to SQL 會保持它的打開狀態不變。我們始終可以訪問此連接,另外還可以使用 Connection 屬性自行關閉它。
 6 
 7  
 8 
 9 //新建一個 標准的ADO.NET連接:
10 
11 SqlConnection nwindConn = new SqlConnection(connString);
12 
13 nwindConn.Open();
14 
15 // ... 其它的ADO.NET數據操作 代碼... //
16 
17 //利用現有的ADO.NET連接來創建一個DataContext:
18 
19 Northwind interop_db = new Northwind(nwindConn);
20 
21 var orders =
22 
23    from o in interop_db.Orders
24 
25    where o.Freight > 500.00M
26 
27    select o;
28 
29 //返回Freight>500.00M的訂單
30 
31 nwindConn.Close();
32 
33  
34 
35 語句描述:這個例子使用預先存在的ADO.NET 連接創建Northwind對象,本例中的查詢返回運費至少為500.00 的所有訂單。
1.連接
 1 2.事務
 2 
 3  
 4 
 5 當我們已經啟動了自己的數據庫事務並且我們希望 DataContext 包含在內時,我們可以向 DataContext 提供此事務。
 6 
 7  
 8 
 9 通過 .NET Framework 創建事務的首選方法是使用 TransactionScope 對象。通過使用此方法,我們可以創建跨數據庫及其他駐留在內存中的資源管理器執行的分布式事務。事務范圍幾乎不需要資源就可以啟動。它們僅在事務范圍內存在多個連接時才將自身提升為分布式事務。
10 
11  
12 
13 using (TransactionScope ts = newTransactionScope())
14 
15 {
16 
17   db.SubmitChanges();
18 
19   ts.Complete();
20 
21 }
22 
23  
24 
25 注意:不能將此方法用於所有數據庫。例如,SqlClient 連接在針對 SQL Server 2000 服務器使用時無法提升系統事務。它采取的方法是,只要它發現有使用事務范圍的情況,它就會自動向完整的分布式事務登記。
26 
27  
28 
29 下面用一個例子說明一下事務的使用方法。在這里,也說明了重用 ADO.NET 命令和 DataContext 之間的同一連接。
30 
31  
32 
33 var q =
34 
35    from p in db.Products
36 
37    where p.ProductID == 3
38 
39    select p;
40 
41 //使用LINQ to SQL查詢出來
42 
43 //新建一個標准的ADO.NET連接:
44 
45 SqlConnection nwindConn = newSqlConnection(connString);
46 
47 nwindConn.Open();
48 
49 //利用現有的 ADO.NET連接來創建一個DataContext:
50 
51 Northwind interop_db = newNorthwind(nwindConn);
52 
53 SqlTransaction nwindTxn =nwindConn.BeginTransaction();
54 
55 try
56 
57 {
58 
59   SqlCommand cmd = new SqlCommand("UPDATE Products SET"
60 
61    +"QuantityPerUnit = 'single item' WHERE ProductID = 3");
62 
63   cmd.Connection = nwindConn;
64 
65    cmd.Transaction = nwindTxn;
66 
67   cmd.ExecuteNonQuery();
68 
69    interop_db.Transaction = nwindTxn;
70 
71   Product prod1 = interop_db.Products.First(p => p.ProductID == 4);
72 
73   Product prod2 = interop_db.Products.First(p => p.ProductID == 5);
74 
75    prod1.UnitsInStock -= 3;
76 
77   prod2.UnitsInStock -= 5;//這有一個錯 誤,不能為負數
78 
79   interop_db.SubmitChanges();
80 
81    nwindTxn.Commit();
82 
83 }
84 
85 catch (Exception e)
86 
87 {
88 
89   // 如果有一個錯誤,所有的操作回滾
90 
91   Console.WriteLine (e.Message);
92 
93 }
94 
95 nwindConn.Close();
96 
97  
98 
99 語句描述:這個例子使用預先存在的 ADO.NET 連接創建 Northwind 對象,然后與此對象共享一個 ADO.NET 事務。此事務既用於通過 ADO.NET 連接執行 SQL 命令,又用於通過 Northwind 對象提交更改。當事務因違反 CHECK 約束而中止時,將回滾所有更改,包括通過 SqlCommand 做出的更改,以及通過Northwind 對象做出的更改。
2.事務

LINQ to SQL語句(20)之存儲過程

存儲過程

 

在我們編寫程序中,往往需要一些存儲過程,在LINQ to SQL中怎么使用呢?也許比原來的更簡單些。下面我們以NORTHWND.MDF數據庫中自帶的幾個存儲過程來理解一下。

 1 1.標量返回
 2 
 3  
 4 
 5 在數據庫中,有名為 Customers Count By Region的存儲過程。該存儲過程返回顧客所在"WA"區域的數量。
 6 
 7  
 8 
 9 ALTER PROCEDURE [dbo]. [NonRowset]
10 
11   (@param1 NVARCHAR(15))
12 
13 AS
14 
15 BEGIN
16 
17   SET NOCOUNT ON;
18 
19    DECLARE @count int
20 
21    SELECT @count = COUNT(*)FROM Customers
22 
23    WHERECustomers.Region = @Param1
24 
25    RETURN @count
26 
27 END
28 
29  
30 
31 我們只要把這個存儲過程拖到O/R設計器內,它自動生成了以下代碼段:
32 
33  
34 
35 [Function(Name = "dbo.[Customers CountBy Region]")]
36 
37 public intCustomers_Count_By_Region([Parameter
38 
39 (DbType = "NVarChar (15)")]string param1)
40 
41 {
42 
43   IExecuteResult result = this.ExecuteMethodCall(this,
44 
45   ((MethodInfo) (MethodInfo.GetCurrentMethod())), param1);
46 
47   return ((int) (result.ReturnValue));
48 
49 }
50 
51  
52 
53 我們需要時,直接調用就可以了,例如:
54 
55  
56 
57 int count = db.CustomersCountByRegion("WA");
58 
59 Console.WriteLine(count);
60 
61  
62 
63 語句描述:這個實例使用存儲過程返回在“WA”地區的客戶數。
1.標量返回
 1 2.單一結果集
 2 
 3  
 4 
 5 從數據庫中返回行集合,並包含用於篩選結果的輸入參數。當我們執行 返回行集合的存儲過程時,會用到結果類,它存儲從存儲過程中返回的結果。
 6 
 7  
 8 
 9 下面的示例表示一個存儲過程,該存儲過程返回客戶行並使用輸入參數來僅返回將“London”列為客戶城市的那些行的固定幾列。 
10 
11  
12 
13 ALTER PROCEDURE [dbo].[Customers By City]
14 
15    -- Add the parameters for the stored procedure here
16 
17    (@param1 NVARCHAR(20))
18 
19 AS
20 
21 BEGIN
22 
23    -- SET NOCOUNT ON added to prevent extra result sets from
24 
25    -- interfering with SELECT statements.
26 
27    SET NOCOUNT ON;
28 
29    SELECT CustomerID, ContactName, CompanyName, City from
30 
31    Customers as c where c.City=@param1
32 
33 END
34 
35  
36 
37 拖到O/R設計器內,它自動生成了以下代碼段:
38 
39  
40 
41 [Function(Name="dbo.[Customers ByCity]")]
42 
43 publicISingleResult<Customers_By_CityResult> Customers_By_City(
44 
45 [Parameter(DbType="NVarChar(20)")]string param1)
46 
47 {
48 
49   IExecuteResult result = this.ExecuteMethodCall(this, (
50 
51   (MethodInfo) (MethodInfo.GetCurrentMethod())), param1);
52 
53   return ((ISingleResult<Customers_By_CityResult>)
54 
55    (result.ReturnValue));
56 
57 }
58 
59  
60 
61 我們用下面的代碼調用:
62 
63  
64 
65 ISingleResult<Customers_By_CityResult>result =
66 
67 db.Customers_By_City("London");
68 
69 foreach (Customers_By_CityResult cust inresult)
70 
71 {
72 
73    Console.WriteLine("CustID={0}; City={1}",cust.CustomerID,
74 
75     cust.City);
76 
77 }
78 
79  
80 
81 語句描述:這個實例使用存儲過程返回在倫敦的客戶的 CustomerID和City。
2.單一結果集
  1 3.多個可能形狀的單一結果集
  2 
  3  
  4 
  5 當存儲過程可以返回多個結果形狀時,返回類型無法強類型化為單個投影形狀。盡管 LINQ to SQL 可以生成所有可能的投影類型,但它無法獲知將以何種順序返回它們。 ResultTypeAttribute 屬性適用於返回多個結果類型的存儲過程,用以指定該過程可以返回的類型的集合。
  6 
  7  
  8 
  9 在下面的 SQL 代碼示例中,結果形狀取決於輸入(param1 = 1或param1 = 2)。我們不知道先返回哪個投影。
 10 
 11  
 12 
 13 ALTER PROCEDURE [dbo].[SingleRowset_MultiShape]
 14 
 15    -- Add the parameters for the stored procedure here
 16 
 17    (@param1 int )
 18 
 19 AS
 20 
 21 BEGIN
 22 
 23    -- SET NOCOUNT ON added to prevent extra result sets from
 24 
 25    -- interfering with SELECT statements.
 26 
 27    SET NOCOUNT ON;
 28 
 29    if(@param1 = 1)
 30 
 31    SELECT * from Customers as c where c.Region = 'WA'
 32 
 33    else if (@param1 = 2)
 34 
 35    SELECT CustomerID, ContactName, CompanyName from
 36 
 37    Customers as c where c.Region = 'WA'
 38 
 39 END
 40 
 41  
 42 
 43 拖到O/R 設計器內,它自動生成了以下代碼段:
 44 
 45  
 46 
 47 [Function (Name="dbo.[Whole Or PartialCustomers Set]")]
 48 
 49 publicISingleResult<Whole_Or_Partial_Customers_SetResult>
 50 
 51 Whole_Or_Partial_Customers_Set([Parameter(DbType="Int")]
 52 
 53 System.Nullable<int> param1)
 54 
 55 {
 56 
 57    IExecuteResult result = this.ExecuteMethodCall(this,
 58 
 59    ((MethodInfo)(MethodInfo.GetCurrentMethod())), param1);
 60 
 61    return ((ISingleResult<Whole_Or_Partial_Customers_SetResult>)
 62 
 63   (result.ReturnValue));
 64 
 65 }
 66 
 67  
 68 
 69 但是,VS2008會把多結果集存儲過程識別為單結果集的存儲過程,默認生成的代碼我們要手動修改一下,要求返回多個結果集,像這樣:
 70 
 71  
 72 
 73 [Function(Name="dbo.[Whole Or PartialCustomers Set]")]
 74 
 75 [ResultType(typeof (WholeCustomersSetResult))]
 76 
 77 [ResultType(typeof(PartialCustomersSetResult))]
 78 
 79 public IMultipleResultsWhole_Or_Partial_Customers_Set([Parameter
 80 
 81 (DbType="Int")]System.Nullable<int> param1)
 82 
 83 {
 84 
 85   IExecuteResult result = this.ExecuteMethodCall(this,
 86 
 87    ((MethodInfo)(MethodInfo.GetCurrentMethod())), param1);
 88 
 89    return ((IMultipleResults)(result.ReturnValue));
 90 
 91 }
 92 
 93  
 94 
 95 我們分別定義了兩個分部類,用於指定返回的類型。WholeCustomersSetResult類 如 下:
 96 
 97  
 98 
 99 public partial classWholeCustomersSetResult
100 
101 {
102 
103   private string _CustomerID;
104 
105   private string _CompanyName;
106 
107   private string _ContactName;
108 
109   private string _ContactTitle;
110 
111   private string _Address;
112 
113    private string _City;
114 
115   private string _Region;
116 
117    private string _PostalCode;
118 
119   private string _Country;
120 
121   private string _Phone;
122 
123   private string _Fax;
124 
125   public WholeCustomersSetResult()
126 
127   {
128 
129   }
130 
131   [Column (Storage = "_CustomerID", DbType ="NChar(5)")]
132 
133   public string CustomerID
134 
135   {
136 
137     get { return this._CustomerID; }
138 
139     set
140 
141     {
142 
143        if ((this._CustomerID != value))
144 
145         this._CustomerID = value;
146 
147     }
148 
149   }
150 
151   [Column(Storage = "_CompanyName", DbType ="NVarChar(40)")]
152 
153   public string CompanyName
154 
155   {
156 
157     get { return this._CompanyName; }
158 
159     set
160 
161     {
162 
163        if ((this._CompanyName != value))
164 
165          this._CompanyName = value;
166 
167     }
168 
169   }
170 
171   [Column (Storage = "_ContactName", DbType ="NVarChar(30) ")]
172 
173   public string ContactName
174 
175   {
176 
177      get { return this._ContactName; }
178 
179     set
180 
181     {
182 
183       if ((this._ContactName != value))
184 
185          this._ContactName = value;
186 
187     }
188 
189   }
190 
191   [Column (Storage = "_ContactTitle", DbType ="NVarChar(30) ")]
192 
193   public string ContactTitle
194 
195   {
196 
197      get { return this._ContactTitle; }
198 
199     set
200 
201     {
202 
203       if ((this._ContactTitle != value))
204 
205          this._ContactTitle = value;
206 
207     }
208 
209   }
210 
211    [Column(Storage = "_Address", DbType = "NVarChar(60)")]
212 
213   public string Address
214 
215   {
216 
217     get { return this._Address; }
218 
219     set
220 
221     {
222 
223       if ((this._Address != value))
224 
225         this._Address = value;
226 
227     }
228 
229   }
230 
231   [Column(Storage = "_City", DbType = "NVarChar(15)")]
232 
233   public string City
234 
235   {
236 
237     get { return this._City; }
238 
239     set
240 
241     {
242 
243       if ((this._City != value))
244 
245         this._City = value;
246 
247     }
248 
249   }
250 
251   [Column(Storage = "_Region", DbType = "NVarChar(15)")]
252 
253   public string Region
254 
255   {
256 
257     get { return this._Region; }
258 
259     set
260 
261     {
262 
263       if ((this._Region != value))
264 
265         this._Region = value;
266 
267     }
268 
269   }
270 
271   [Column(Storage = "_PostalCode", DbType ="NVarChar(10)")]
272 
273    public string PostalCode
274 
275   {
276 
277     get { return this._PostalCode; }
278 
279     set
280 
281     {
282 
283        if ((this._PostalCode != value))
284 
285         this._PostalCode = value;
286 
287     }
288 
289   }
290 
291   [Column(Storage = "_Country", DbType ="NVarChar(15)")]
292 
293    public string Country
294 
295   {
296 
297     get { return this._Country; }
298 
299     set
300 
301     {
302 
303       if ((this._Country != value))
304 
305         this._Country = value;
306 
307     }
308 
309   }
310 
311   [Column(Storage = "_Phone", DbType ="NVarChar(24)")]
312 
313    public string Phone
314 
315   {
316 
317     get { return this._Phone; }
318 
319     set
320 
321     {
322 
323       if ((this._Phone != value))
324 
325         this._Phone = value;
326 
327     }
328 
329   }
330 
331   [Column(Storage = "_Fax", DbType ="NVarChar(24)")]
332 
333   public string Fax
334 
335   {
336 
337     get { return this._Fax; }
338 
339     set
340 
341     {
342 
343       if ((this._Fax != value))
344 
345         this._Fax = value;
346 
347     }
348 
349   }
350 
351 }
352 
353  
354 
355 PartialCustomersSetResult類 如下:
356 
357  
358 
359 public partial classPartialCustomersSetResult
360 
361 {
362 
363   private string _CustomerID;
364 
365   private string _ContactName;
366 
367   private string _CompanyName;
368 
369   public PartialCustomersSetResult()
370 
371   {
372 
373   }
374 
375   [Column (Storage = "_CustomerID", DbType ="NChar(5)")]
376 
377   public string CustomerID
378 
379   {
380 
381     get { return this._CustomerID; }
382 
383     set
384 
385     {
386 
387        if ((this._CustomerID != value))
388 
389         this._CustomerID = value;
390 
391     }
392 
393   }
394 
395   [Column(Storage = "_ContactName", DbType ="NVarChar(30)")]
396 
397   public string ContactName
398 
399   {
400 
401     get { return this._ContactName; }
402 
403     set
404 
405     {
406 
407        if ((this._ContactName != value))
408 
409          this._ContactName = value;
410 
411     }
412 
413   }
414 
415   [Column (Storage = "_CompanyName", DbType ="NVarChar(40) ")]
416 
417   public string CompanyName
418 
419   {
420 
421      get { return this._CompanyName; }
422 
423     set
424 
425     {
426 
427       if ((this._CompanyName != value))
428 
429          this._CompanyName = value;
430 
431     }
432 
433   }
434 
435 }
436 
437  
438 
439 這樣就可以使用了,下面代碼直接調用,分別返回各自的結果集合。
440 
441  
442 
443 //返回全部Customer結果集
444 
445 IMultipleResults result =db.Whole_Or_Partial_Customers_Set(1);
446 
447 IEnumerable<WholeCustomersSetResult>shape1 =
448 
449 result.GetResult<WholeCustomersSetResult>();
450 
451 foreach (WholeCustomersSetResult compNamein shape1)
452 
453 {
454 
455    Console.WriteLine(compName.CompanyName);
456 
457 }
458 
459 //返回部分 Customer結果集
460 
461 result =db.Whole_Or_Partial_Customers_Set(2);
462 
463 IEnumerable<PartialCustomersSetResult>shape2 =
464 
465 result.GetResult<PartialCustomersSetResult>();
466 
467 foreach (PartialCustomersSetResult con inshape2)
468 
469 {
470 
471    Console.WriteLine(con.ContactName);
472 
473 }
474 
475  
476 
477 語句描述:這個實例使用存儲過程返回“WA”地區中的一組客戶。返回的結果集形狀取決於傳入的參數。如果參數等於 1,則返回所有客戶屬性。如果參數等於2,則返回ContactName屬性。
3.多個可能形狀的單一結果集
  1 4.多個結果集
  2 
  3  
  4 
  5 這種存儲過程可以生成多個結果形狀,但我們已經知道結果的返回順序。
  6 
  7  
  8 
  9 下面是一個按順序返回多個結果集的存儲過程Get Customer And Orders。 返回顧客ID為"SEVES"的顧客和他們所有的訂單。
 10 
 11  
 12 
 13 ALTER PROCEDURE [dbo].[Get Customer AndOrders]
 14 
 15 (@CustomerID nchar(5))
 16 
 17   -- Add the parameters for the stored procedure here
 18 
 19 AS
 20 
 21 BEGIN
 22 
 23    -- SET NOCOUNT ON added to prevent extra result sets from
 24 
 25   -- interfering with SELECT statements.
 26 
 27   SET NOCOUNT ON;
 28 
 29    SELECT * FROM Customers AS c WHERE c.CustomerID = @CustomerID 
 30 
 31   SELECT * FROM Orders AS o WHERE o.CustomerID = @CustomerID
 32 
 33 END
 34 
 35  
 36 
 37 拖到設計器代碼如下:
 38 
 39  
 40 
 41 [Function (Name="dbo.[Get Customer AndOrders]")]
 42 
 43 publicISingleResult<Get_Customer_And_OrdersResult>
 44 
 45 Get_Customer_And_Orders([Parameter(Name="CustomerID",
 46 
 47 DbType="NChar(5)")] stringcustomerID)
 48 
 49 {
 50 
 51    IExecuteResult result = this.ExecuteMethodCall(this,
 52 
 53    ((MethodInfo)(MethodInfo.GetCurrentMethod())), customerID);
 54 
 55    return ((ISingleResult<Get_Customer_And_OrdersResult>)
 56 
 57    (result.ReturnValue));
 58 
 59 }
 60 
 61  
 62 
 63 同樣,我們要修改自動生成的代碼:
 64 
 65  
 66 
 67 [Function(Name="dbo.[Get Customer AndOrders] ")]
 68 
 69 [ResultType(typeof(CustomerResultSet))]
 70 
 71 [ResultType(typeof(OrdersResultSet))]
 72 
 73 public IMultipleResultsGet_Customer_And_Orders
 74 
 75 ([Parameter(Name="CustomerID",DbType="NChar(5)")]
 76 
 77 string customerID)
 78 
 79 {
 80 
 81   IExecuteResult result = this.ExecuteMethodCall(this,
 82 
 83   ((MethodInfo) (MethodInfo.GetCurrentMethod())), customerID);
 84 
 85   return ((IMultipleResults)(result.ReturnValue));
 86 
 87 }
 88 
 89  
 90 
 91 同樣,自己手寫類,讓其存儲過程返回各自的結果集。
 92 
 93  
 94 
 95 CustomerResultSet類
 96 
 97  
 98 
 99 public partial class CustomerResultSet
100 
101 {
102 
103   private string _CustomerID;
104 
105   private string _CompanyName;
106 
107   private string _ContactName;
108 
109   private string _ContactTitle;
110 
111   private string _Address;
112 
113    private string _City;
114 
115   private string _Region;
116 
117    private string _PostalCode;
118 
119   private string _Country;
120 
121   private string _Phone;
122 
123   private string _Fax;
124 
125   public CustomerResultSet()
126 
127   {
128 
129   }
130 
131   [Column(Storage = "_CustomerID", DbType ="NChar(5)")]
132 
133    public string CustomerID
134 
135   {
136 
137     get { return this._CustomerID; }
138 
139     set
140 
141     {
142 
143        if ((this._CustomerID != value))
144 
145         this._CustomerID = value;
146 
147     }
148 
149   }
150 
151   [Column(Storage = "_CompanyName", DbType ="NVarChar(40)")]
152 
153   public string CompanyName
154 
155   {
156 
157     get { return this._CompanyName; }
158 
159     set
160 
161     {
162 
163        if ((this._CompanyName != value))
164 
165          this._CompanyName = value;
166 
167     }
168 
169   }
170 
171   [Column (Storage = "_ContactName", DbType ="NVarChar(30) ")]
172 
173   public string ContactName
174 
175   {
176 
177      get { return this._ContactName; }
178 
179     set
180 
181     {
182 
183       if ((this._ContactName != value))
184 
185          this._ContactName = value;
186 
187     }
188 
189   }
190 
191   [Column (Storage = "_ContactTitle", DbType ="NVarChar(30) ")]
192 
193   public string ContactTitle
194 
195   {
196 
197      get { return this._ContactTitle; }
198 
199     set
200 
201     {
202 
203       if ((this._ContactTitle != value))
204 
205          this._ContactTitle = value;
206 
207     }
208 
209   }
210 
211    [Column(Storage = "_Address", DbType = "NVarChar(60)")]
212 
213   public string Address
214 
215   {
216 
217     get { return this._Address; }
218 
219     set
220 
221     {
222 
223       if ((this._Address != value))
224 
225         this._Address = value;
226 
227     }
228 
229   }
230 
231   [Column(Storage = "_City", DbType ="NVarChar(15)")]
232 
233   public string City
234 
235   {
236 
237     get { return this._City; }
238 
239     set
240 
241     {
242 
243       if ((this._City != value))
244 
245         this._City = value;
246 
247     }
248 
249   }
250 
251   [Column(Storage = "_Region", DbType = "NVarChar(15)")]
252 
253   public string Region
254 
255   {
256 
257     get { return this._Region; }
258 
259     set
260 
261     {
262 
263       if ((this._Region != value))
264 
265         this._Region = value;
266 
267     }
268 
269   }
270 
271   [Column(Storage = "_PostalCode", DbType ="NVarChar(10)")]
272 
273    public string PostalCode
274 
275   {
276 
277     get { return this._PostalCode; }
278 
279     set
280 
281     {
282 
283        if ((this._PostalCode != value))
284 
285         this._PostalCode = value;
286 
287     }
288 
289   }
290 
291   [Column(Storage = "_Country", DbType ="NVarChar(15)")]
292 
293    public string Country
294 
295   {
296 
297     get { return this._Country; }
298 
299     set
300 
301     {
302 
303       if ((this._Country != value))
304 
305         this._Country = value;
306 
307     }
308 
309   }
310 
311   [Column(Storage = "_Phone", DbType ="NVarChar(24)")]
312 
313    public string Phone
314 
315   {
316 
317     get { return this._Phone; }
318 
319     set
320 
321     {
322 
323       if ((this._Phone != value))
324 
325         this._Phone = value;
326 
327     }
328 
329   }
330 
331   [Column(Storage = "_Fax", DbType ="NVarChar(24)")]
332 
333   public string Fax
334 
335   {
336 
337     get { return this._Fax; }
338 
339     set
340 
341     {
342 
343       if ((this._Fax != value))
344 
345         this._Fax = value;
346 
347     }
348 
349   }
350 
351 }
352 
353  
354 
355 OrdersResultSet 類
356 
357  
358 
359 public partial class OrdersResultSet
360 
361 {
362 
363   private System.Nullable<int> _OrderID;
364 
365   private string _CustomerID;
366 
367   private System.Nullable<int> _EmployeeID;
368 
369   private System.Nullable<System.DateTime> _OrderDate;
370 
371   private System.Nullable<System.DateTime> _RequiredDate;
372 
373   private System.Nullable<System.DateTime> _ShippedDate;
374 
375   private System.Nullable<int> _ShipVia;
376 
377   private System.Nullable<decimal> _Freight;
378 
379    private string _ShipName;
380 
381   private string _ShipAddress;
382 
383   private string _ShipCity;
384 
385   private string _ShipRegion;
386 
387   private string _ShipPostalCode;
388 
389   private string _ShipCountry;
390 
391   public OrdersResultSet()
392 
393   {
394 
395   }
396 
397   [Column(Storage = "_OrderID", DbType = "Int")]
398 
399   public System.Nullable<int> OrderID
400 
401   {
402 
403     get { return this._OrderID; }
404 
405     set
406 
407     {
408 
409       if ((this._OrderID != value))
410 
411         this._OrderID = value;
412 
413     }
414 
415   }
416 
417   [Column(Storage = "_CustomerID", DbType ="NChar(5)")]
418 
419   public string CustomerID
420 
421   {
422 
423     get { return this._CustomerID; }
424 
425     set
426 
427     {
428 
429       if ((this._CustomerID != value))
430 
431         this._CustomerID = value;
432 
433     }
434 
435   }
436 
437    [Column(Storage = "_EmployeeID", DbType ="Int")]
438 
439   public System.Nullable<int> EmployeeID
440 
441   {
442 
443     get { return this._EmployeeID; }
444 
445     set
446 
447     {
448 
449       if ((this._EmployeeID != value))
450 
451         this._EmployeeID = value;
452 
453     }
454 
455   }
456 
457    [Column(Storage = "_OrderDate", DbType ="DateTime")]
458 
459   public System.Nullable<System.DateTime> OrderDate
460 
461   {
462 
463     get { return this._OrderDate; }
464 
465     set
466 
467     {
468 
469       if ((this._OrderDate != value))
470 
471          this._OrderDate = value;
472 
473     }
474 
475   }
476 
477   [Column (Storage = "_RequiredDate", DbType ="DateTime")]
478 
479   public System.Nullable<System.DateTime> RequiredDate
480 
481   {
482 
483     get { return this._RequiredDate; }
484 
485     set
486 
487     {
488 
489       if ((this._RequiredDate != value))
490 
491          this._RequiredDate = value;
492 
493     }
494 
495   }
496 
497    [Column(Storage = "_ShippedDate", DbType ="DateTime")]
498 
499   public System.Nullable<System.DateTime> ShippedDate
500 
501   {
502 
503     get { return this._ShippedDate; }
504 
505     set
506 
507      {
508 
509       if ((this._ShippedDate != value))
510 
511         this._ShippedDate = value;
512 
513     }
514 
515   }
516 
517    [Column(Storage = "_ShipVia", DbType = "Int")]
518 
519   public System.Nullable<int> ShipVia
520 
521   {
522 
523     get { return this._ShipVia; }
524 
525     set
526 
527     {
528 
529       if ((this._ShipVia != value))
530 
531          this._ShipVia = value;
532 
533     }
534 
535   }
536 
537   [Column (Storage = "_Freight", DbType ="Money")]
538 
539   public System.Nullable<decimal> Freight
540 
541   {
542 
543     get { return this._Freight; }
544 
545     set
546 
547     {
548 
549       if ((this._Freight != value))
550 
551          this._Freight = value;
552 
553     }
554 
555   }
556 
557   [Column (Storage = "_ShipName", DbType ="NVarChar(40)")]
558 
559   public string ShipName
560 
561   {
562 
563     get { return this._ShipName; }
564 
565     set
566 
567     {
568 
569       if ((this._ShipName != value))
570 
571         this._ShipName = value;
572 
573     }
574 
575   }
576 
577   [Column(Storage = "_ShipAddress", DbType ="NVarChar(60)")]
578 
579   public string ShipAddress
580 
581   {
582 
583     get { return this._ShipAddress; }
584 
585     set
586 
587     {
588 
589        if ((this._ShipAddress != value))
590 
591          this._ShipAddress = value;
592 
593     }
594 
595   }
596 
597   [Column (Storage = "_ShipCity", DbType ="NVarChar(15)")]
598 
599   public string ShipCity
600 
601   {
602 
603     get { return this._ShipCity; }
604 
605     set
606 
607     {
608 
609       if ((this._ShipCity != value))
610 
611         this._ShipCity = value;
612 
613     }
614 
615   }
616 
617   [Column(Storage = "_ShipRegion", DbType ="NVarChar(15)")]
618 
619    public string ShipRegion
620 
621   {
622 
623     get { return this._ShipRegion; }
624 
625     set
626 
627     {
628 
629        if ((this._ShipRegion != value))
630 
631         this._ShipRegion = value;
632 
633     }
634 
635   }
636 
637   [Column(Storage = "_ShipPostalCode", DbType ="NVarChar(10)")]
638 
639   public string ShipPostalCode
640 
641   {
642 
643     get { return this._ShipPostalCode; }
644 
645     set
646 
647     {
648 
649       if ((this._ShipPostalCode != value))
650 
651          this._ShipPostalCode = value;
652 
653     }
654 
655   }
656 
657    [Column(Storage = "_ShipCountry", DbType = "NVarChar(15)")]
658 
659   public string ShipCountry
660 
661   {
662 
663     get { return this._ShipCountry; }
664 
665     set
666 
667     {
668 
669       if ((this._ShipCountry != value))
670 
671          this._ShipCountry = value;
672 
673     }
674 
675   }
676 
677 }
678 
679  
680 
681  
682 
683 這時,只要調用就可以了。
684 
685  
686 
687 IMultipleResults result =db.Get_Customer_And_Orders("SEVES");
688 
689 //返回 Customer結果集
690 
691 IEnumerable<CustomerResultSet>customer =
692 
693 result.GetResult<CustomerResultSet>();
694 
695 //返回Orders結果集
696 
697 IEnumerable<OrdersResultSet> orders =
698 
699 result.GetResult<OrdersResultSet>();
700 
701 //在這里,我們讀取CustomerResultSet中的數據
702 
703 foreach (CustomerResultSet cust incustomer)
704 
705 {
706 
707   Console.WriteLine(cust.CustomerID);
708 
709 }
710 
711  
712 
713 語句描述:這個實例使用存儲過程返回客戶“SEVES”及其所有訂單。
4.多個結果集
 1 5.帶輸出參數
 2 
 3  
 4 
 5 LINQ to SQL 將輸出參數映射到引用參數 ,並且對於值類型,它將參數聲明為可以為null。
 6 
 7  
 8 
 9 下面的示例帶有單個輸入參數(客戶 ID)並返回一個輸出參數(該客戶的總銷售額)。
10 
11  
12 
13 ALTER PROCEDURE [dbo].[CustOrderTotal]
14 
15 @CustomerID nchar(5),
16 
17 @TotalSales money OUTPUT
18 
19 AS
20 
21 SELECT @TotalSales =SUM(OD.UNITPRICE*(1-OD.DISCOUNT) * OD.QUANTITY)
22 
23 FROM ORDERS O, "ORDER DETAILS" OD
24 
25 where O.CUSTOMERID = @CustomerID AND O.ORDERID= OD.ORDERID
26 
27  
28 
29 把這個存儲過程拖到設計器中,圖片如下:
30 
31  
32 
33  
34 
35 其生成代碼如下:
36 
37  
38 
39 [Function(Name="dbo.CustOrderTotal")]
40 
41 public int CustOrderTotal (
42 
43 [Parameter(Name="CustomerID",DbType="NChar(5) ")]string customerID,
44 
45 [Parameter (Name="TotalSales",DbType="Money")]
46 
47  ref System.Nullable<decimal> totalSales)
48 
49 {
50 
51    IExecuteResult result = this.ExecuteMethodCall(this,
52 
53    ((MethodInfo)(MethodInfo.GetCurrentMethod())),
54 
55   customerID, totalSales);
56 
57   totalSales = ((System.Nullable<decimal>)
58 
59   (result.GetParameterValue(1)));
60 
61   return ((int) (result.ReturnValue));
62 
63 }
64 
65  
66 
67 我們使用下面的語句調用此存儲過程:注意:輸出參數是按引用傳遞的,以支持參數為“in/out”的方案。在這種情況下,參數僅為“out”。
68 
69  
70 
71 decimal? totalSales = 0;
72 
73 string customerID = "ALFKI";
74 
75 db.CustOrderTotal(customerID, reftotalSales);
76 
77 Console.WriteLine("Total Sales forCustomer '{0}' = {1:C}",
78 
79 customerID, totalSales);
80 
81  
82 
83 語句描述:這個實例使用返回 Out 參數的存儲過程。
84 
85  
86 
87 好了,就說到這里了,其增刪改操作同理。相信大家通過這5個實例理解了存儲過程。
5.帶輸出參數

LINQ to SQL語句(21)之用戶定義函數

我們可以在LINQ to SQL中使用用戶定義函數。只要把用戶定義函數拖到O/R設計器中,LINQ to SQL自動使用FunctionAttribute屬性和ParameterAttribute屬性(如果需要)將其函數指定為方法。這時,我們只需簡單調用即可。

 

在這里注意:使用用戶定義函數的時候必須滿足以下形式之一,否則會出現InvalidOperationException異常情況。

 

具有正確映射屬性的方法調用的函數。這里使用FunctionAttribute屬性和 ParameterAttribute屬性。

 

特定於LINQ to SQL的靜態SQL方法。

 

.NET Framework方法支持的函數。

 

下面介紹幾個例子:

 1 1.在Select中使用用戶定義的標量函數
 2 
 3  
 4 
 5 所謂標量函數是指返回在 RETURNS 子句中定義的類型的單個數據值。可以使用所有標量數據類型,包括 bigint 和 sql_variant。不支持 timestamp 數據類型、用戶定義數據類型和非標量類型(如 table 或 cursor)。在 BEGIN...END 塊中定義的函數主體包含返回該值的 Transact-SQL 語句系列。返回類型可以是除 text、ntext、image 、cursor 和 timestamp 之外的任何數據類型。我們在系統自帶的 NORTHWND.MDF數據庫中,有3個自定義函數,這里使用 TotalProductUnitPriceByCategory,其代碼如下:
 6 
 7  
 8 
 9 ALTER FUNCTION[dbo].[TotalProductUnitPriceByCategory]
10 
11 (@categoryID int)
12 
13 RETURNS Money
14 
15 AS
16 
17 BEGIN
18 
19   -- Declare the return variable here
20 
21   DECLARE @ResultVar Money
22 
23   -- Add the T-SQL statements to compute the return value here
24 
25   SELECT @ResultVar = (Select SUM(UnitPrice)
26 
27             from Products
28 
29             where CategoryID = @categoryID)
30 
31   -- Return the result of the function
32 
33   RETURN @ResultVar
34 
35 END
36 
37  
38 
39 我們將其拖到設計器中,LINQ to SQL通過使用 FunctionAttribute 屬性將類中定義的客戶端方法映射到用戶定義的函數。請注意,這個方法體會構造一個捕獲方法調用意向的表達式,並將該表達式傳遞給 DataContext 進行轉換和執行。
40 
41  
42 
43 [Function(Name="dbo.TotalProductUnitPriceByCategory",
44 
45 IsComposable=true)]
46 
47 public System.Nullable<decimal>TotalProductUnitPriceByCategory(
48 
49 [Parameter (DbType="Int")]System.Nullable<int> categoryID)
50 
51 {
52 
53   return ((System.Nullable<decimal>)(this.ExecuteMethodCall(this,
54 
55   ((MethodInfo) (MethodInfo.GetCurrentMethod())), categoryID)
56 
57    .ReturnValue));
58 
59 }
60 
61  
62 
63 我們使用時,可以用以下代碼來調用:
64 
65  
66 
67 var q = from c in db.Categories
68 
69     select new
70 
71     {
72 
73       c.CategoryID,
74 
75        TotalUnitPrice =
76 
77          db.TotalProductUnitPriceByCategory(c.CategoryID)
78 
79     };
80 
81  
82 
83 這時,LINQ to SQL自動生成SQL語句如下:
84 
85  
86 
87 SELECT [t0].[CategoryID],CONVERT(Decimal(29,4),
88 
89 [dbo].[TotalProductUnitPriceByCategory]([t0].[CategoryID]))
90 
91 AS [TotalUnitPrice] FROM [dbo].[Categories]AS [t0]
1.在Select中使用用戶定義的標量函數
 1 2.在Where從句中 使用用戶定義的標量函數
 2 
 3 這個例子使用方法同上一個例子原理基本相同了,MinUnitPriceByCategory自定義函數如下:
 4 
 5  
 6 
 7 ALTER FUNCTION[dbo].[MinUnitPriceByCategory]
 8 
 9 (@categoryID INT
10 
11 )
12 
13 RETURNS Money
14 
15 AS
16 
17 BEGIN
18 
19   -- Declare the return variable here
20 
21   DECLARE @ResultVar Money
22 
23   -- Add the T -SQL statements to compute the return value here
24 
25   SELECT @ResultVar = MIN(p.UnitPrice) FROM Products as p
26 
27   WHERE p.CategoryID = @categoryID
28 
29   -- Return the result of the function
30 
31   RETURN @ResultVar
32 
33 END
34 
35  
36 
37 拖到設計器中,生成代碼如下:
38 
39  
40 
41 [Function (Name="dbo.MinUnitPriceByCategory",IsComposable=true)]
42 
43 public System.Nullable<decimal>MinUnitPriceByCategory(
44 
45 [Parameter(DbType="Int")]System.Nullable<int> categoryID)
46 
47 {
48 
49   return ((System.Nullable<decimal>) (this.ExecuteMethodCall(
50 
51   this, ((MethodInfo) (MethodInfo.GetCurrentMethod())),
52 
53    categoryID).ReturnValue));
54 
55 }
56 
57  
58 
59 這時可以使用了:注意這里在 LINQ to SQL 查詢中,對生成的用戶定義函數方法 MinUnitPriceByCategory的內聯調用。此函數不會立即執行,這是因為查詢會延 遲執行。延遲執行的查詢中包含的函數直到此查詢執行時才會執行。為此查詢生成的 SQL 會轉換成對數據庫中用戶定義函數的調用(請參見此查詢后面的生成的 SQL語句),當在查詢外部調用這個函數時,LINQ to SQL 會用方法調用表達式創建一個簡單查詢並執行。 
60 
61  
62 
63 var q =
64 
65   from p in db.Products
66 
67   where p.UnitPrice ==
68 
69    db.MinUnitPriceByCategory(p.CategoryID)
70 
71   select p;
72 
73  
74 
75 它自動生成的SQL語句如下:
76 
77  
78 
79 SELECT [t0]. [ProductID],[t0].[ProductName], [t0].[SupplierID],
80 
81 [t0]. [CategoryID],[t0].[QuantityPerUnit],[t0].[UnitPrice],
82 
83 [t0]. [UnitsInStock],[t0].[UnitsOnOrder],[t0].[ReorderLevel],
84 
85 [t0]. [Discontinued]FROM [dbo].[Products]AS [t0]
86 
87 WHERE [t0]. [UnitPrice] =
88 
89 [dbo].[MinUnitPriceByCategory]([t0].[CategoryID])
2.在Where從句中 使用用戶定義的標量函數
  1 3.使用用戶定義的表值函數
  2 
  3  
  4 
  5 表值函數返回單個行集(與存儲過程不同,存儲過程可返回多個結果形狀)。由於表值函數的返回類型為 Table,因此在 SQL 中可以使用表的任何地方均可以使用表值函數。此外,您還可以完全像處理表那樣來處理表值函數。
  6 
  7  
  8 
  9 下面的 SQL 用戶定義函數顯式聲明其返回一個 TABLE。因此,隱式定義了所返回的行集結構。
 10 
 11 ALTER FUNCTION[dbo].[ProductsUnderThisUnitPrice]
 12 
 13 (@price Money
 14 
 15 )
 16 
 17 RETURNS TABLE
 18 
 19 AS
 20 
 21 RETURN
 22 
 23   SELECT *
 24 
 25    FROM Products as P
 26 
 27   Where p.UnitPrice < @price
 28 
 29  
 30 
 31 拖到設計器中,LINQ to SQL 按如下方式映射此函數:
 32 
 33  
 34 
 35 [Function(Name="dbo.ProductsUnderThisUnitPrice",
 36 
 37 IsComposable=true)]
 38 
 39 publicIQueryable<ProductsUnderThisUnitPriceResult>
 40 
 41 ProductsUnderThisUnitPrice([Parameter(DbType="Money")]
 42 
 43 System.Nullable<decimal> price)
 44 
 45 {
 46 
 47   return this.CreateMethodCallQuery
 48 
 49    <ProductsUnderThisUnitPriceResult>(this,
 50 
 51   ((MethodInfo) (MethodInfo.GetCurrentMethod())), price);
 52 
 53 }
 54 
 55  
 56 
 57 這時我們小小的修改一下Discontinued屬性為可空的bool類型。
 58 
 59  
 60 
 61 private System.Nullable<bool>_Discontinued;
 62 
 63 public System.Nullable<bool>Discontinued
 64 
 65 {
 66 
 67 }
 68 
 69  
 70 
 71 我們可以這樣調用使用了:
 72 
 73  
 74 
 75 var q = from p indb.ProductsUnderThisUnitPrice(10.25M)
 76 
 77     where ! (p.Discontinued ?? false)
 78 
 79     select p;
 80 
 81  
 82 
 83 其生成 SQL語句如下:
 84 
 85  
 86 
 87 SELECT [t0].[ProductID],[t0].[ProductName], [t0].[SupplierID],
 88 
 89 [t0].[CategoryID], [t0].[QuantityPerUnit],[t0].[UnitPrice],
 90 
 91 [t0].[UnitsInStock], [t0].[UnitsOnOrder],[t0].[ReorderLevel],
 92 
 93 [t0].[Discontinued]
 94 
 95 FROM [dbo].[ProductsUnderThisUnitPrice](@p0) AS [t0]
 96 
 97 WHERE NOT ((COALESCE([t0].[Discontinued],@p1)) = 1)
 98 
 99 -- @p0: Input Money (Size = 0; Prec = 19;Scale = 4) [10.25]
100 
101 -- @p1: Input Int (Size = 0; Prec = 0;Scale = 0) [0]
3.使用用戶定義的表值函數
 1 4.以聯接方式使用用戶定義的表值函數
 2 
 3  
 4 
 5 我們利用上面的ProductsUnderThisUnitPrice用戶定義函數,在 LINQ to SQL 中, 調用如下:
 6 
 7  
 8 
 9 var q =
10 
11   from c in db.Categories
12 
13   join p in db.ProductsUnderThisUnitPrice(8.50M) on
14 
15    c.CategoryID equals p.CategoryID into prods
16 
17   from p in prods
18 
19   select new
20 
21   {
22 
23     c.CategoryID,
24 
25     c.CategoryName,
26 
27     p.ProductName,
28 
29      p.UnitPrice
30 
31   };
32 
33  
34 
35 其生成的 SQL 代碼說明對此函數返回的表執行聯接。
36 
37  
38 
39 SELECT [t0].[CategoryID], [t0]. [CategoryName],
40 
41 [t1].[ProductName], [t1].[UnitPrice]
42 
43 FROM [dbo].[Categories] AS [t0]
44 
45 CROSS JOIN [dbo].[ProductsUnderThisUnitPrice](@p0) AS [t1]
46 
47 WHERE ([t0]. [CategoryID]) =[t1].[CategoryID]
48 
49 -- @p0: Input Money (Size = 0; Prec = 19;Scale = 4) [8.50]
4.以聯接方式使用用戶定義的表值函數

LINQ to SQL語句(22)之DataContext

DataContext

 

DataContext作為LINQ to SQL框架的主入口點,為我們 提供了一些方法和屬性,本文用幾個例子說明DataContext幾個典型的應用。

  1 創建和刪除數據庫
  2 
  3  
  4 
  5 CreateDatabase方法用於在服務器上創建數據庫。
  6 
  7  
  8 
  9 DeleteDatabase方法用於刪除由DataContext連接字符串標識的數據 庫。
 10 
 11  
 12 
 13 數據庫的名稱有以下方法來定義:
 14 
 15  
 16 
 17 如果數據庫在連接字符串中標識,則使用該連接字符串的名稱。
 18 
 19  
 20 
 21 如果存在DatabaseAttribute屬性 (Attribute),則將其Name屬性(Property)用作數據庫的名稱。
 22 
 23  
 24 
 25 如果連接字符串中沒有數據庫標記,並且使用強類型的DataContext,則會檢查與 DataContext繼承類名稱相同的數據庫。如果使用弱類型的DataContext,則會引發異常。
 26 
 27  
 28 
 29 如果已通過使用文件名創建了DataContext,則會創建與該文件名相對應的數據庫。
 30 
 31  
 32 
 33 我們首先用實體類描述關系數據庫表和列的結構的屬性。再調用DataContext的CreateDatabase方法,LINQ to SQL會用我們的定義的實體類結構來構造一個新的數據庫實例。還可以通過使用 .mdf 文件或只使用目錄名(取決於連接字符串),將 CreateDatabase與SQL Server一起使用。 LINQ to SQL使用連接字符串來定義要創建的數據庫和作為數據庫創建位置的服務器。
 34 
 35  
 36 
 37 說了這么多,用一段實例說明一下吧!
 38 
 39  
 40 
 41 首先,我們新建一個NewCreateDB類用於創建一個名為NewCreateDB.mdf的新數據庫,該數據庫有一個Person表,有三個字段,分別為PersonID、PersonName、Age。
 42 
 43  
 44 
 45 public class NewCreateDB : DataContext
 46 
 47 {
 48 
 49   public Table<Person> Persons;
 50 
 51   public NewCreateDB (string connection)
 52 
 53     :
 54 
 55     base(connection)
 56 
 57   {
 58 
 59   }
 60 
 61   public NewCreateDB(System.Data.IDbConnection connection)
 62 
 63     :
 64 
 65     base(connection)
 66 
 67   {
 68 
 69   }
 70 
 71 }
 72 
 73 [Table(Name = "Person")]
 74 
 75 public partial class Person :INotifyPropertyChanged
 76 
 77 {
 78 
 79   private int _PersonID;
 80 
 81   private string _PersonName;
 82 
 83   private System.Nullable<int> _Age;
 84 
 85   public Person() { }
 86 
 87   [Column(Storage = "_PersonID", DbType = "INT",
 88 
 89     IsPrimaryKey = true)]
 90 
 91   public int PersonID
 92 
 93   {
 94 
 95     get { return this._PersonID; }
 96 
 97     set
 98 
 99     {
100 
101       if ((this._PersonID != value))
102 
103       {
104 
105          this.OnPropertyChanged("PersonID");
106 
107          this._PersonID = value;
108 
109         this.OnPropertyChanged ("PersonID");
110 
111       }
112 
113     }
114 
115   }
116 
117   [Column(Storage = "_PersonName", DbType ="NVarChar(30)")]
118 
119   public string PersonName
120 
121    {
122 
123     get { return this._PersonName; }
124 
125     set
126 
127     {
128 
129       if ((this._PersonName != value))
130 
131       {
132 
133         this.OnPropertyChanged ("PersonName");
134 
135         this._PersonName = value;
136 
137         this.OnPropertyChanged ("PersonName");
138 
139       }
140 
141     }
142 
143   }
144 
145   [Column(Storage = "_Age", DbType = "INT")]
146 
147   public System.Nullable<int> Age
148 
149   {
150 
151     get { return this._Age; }
152 
153     set
154 
155     {
156 
157       if ((this._Age != value))
158 
159        {
160 
161         this.OnPropertyChanged("Age");
162 
163         this._Age = value;
164 
165          this.OnPropertyChanged("Age");
166 
167       }
168 
169     }
170 
171   }
172 
173   public event PropertyChangedEventHandler PropertyChanged;
174 
175   protected virtual void OnPropertyChanged (string PropertyName)
176 
177   {
178 
179     if ((this.PropertyChanged != null))
180 
181     {
182 
183        this.PropertyChanged(this,
184 
185         new PropertyChangedEventArgs(PropertyName));
186 
187     }
188 
189   }
190 
191 }
192 
193  
194 
195 接下來的一段代碼先創建一個數據庫,在調用 CreateDatabase后,新的數據庫就會存在並且會接受一般的查詢和命令。接着插入一條記錄並且查詢。最后刪除這個數據庫。
196 
197  
198 
199 //1.新建一個臨時 文件夾來存放新建的數據庫
200 
201 string userTempFolder =Environment.GetEnvironmentVariable
202 
203 ("SystemDrive") +@"YJingLee";
204 
205 Directory.CreateDirectory (userTempFolder);
206 
207 //2.新建數據庫NewCreateDB
208 
209 string userMDF = System.IO.Path.Combine(userTempFolder,
210 
211   @"NewCreateDB.mdf");
212 
213 string connStr = String.Format (@"DataSource=.SQLEXPRESS;
214 
215 AttachDbFilename={0};IntegratedSecurity=True;
216 
217 Connect Timeout=30;User Instance=True;
218 
219 Integrated Security = SSPI;",userMDF);
220 
221 NewCreateDB newDB = newNewCreateDB(connStr);
222 
223 newDB.CreateDatabase();
224 
225 //3.插入 數據並查詢
226 
227 var newRow = new Person
228 
229 {
230 
231    PersonID = 1,
232 
233    PersonName = "YJingLee",
234 
235    Age = 22
236 
237 };
238 
239 newDB.Persons.InsertOnSubmit(newRow);
240 
241 newDB.SubmitChanges();
242 
243 var q = from x in newDB.Persons
244 
245      select x;
246 
247 //4.刪除數據庫
248 
249 newDB.DeleteDatabase();
250 
251 //5.刪除臨時目錄
252 
253 Directory.Delete (userTempFolder);
創建和刪除數據庫
 1 數據庫驗證
 2 
 3  
 4 
 5 DatabaseExists方法用於 嘗試通過使用DataContext中的連接打開數據庫,如果成功返回true。
 6 
 7  
 8 
 9 下面代碼說明是否存在Northwind數據庫和NewCreateDB數據庫。
10 
11  
12 
13 // 檢測Northwind數據庫是否存在
14 
15 if (db.DatabaseExists())
16 
17    Console.WriteLine("Northwind數據庫存在");
18 
19 else
20 
21   Console.WriteLine("Northwind數據庫不存在");
22 
23 //檢測 NewCreateDB數據庫是否存在
24 
25 string userTempFolder =Environment.GetEnvironmentVariable("Temp");
26 
27 string userMDF =System.IO.Path.Combine(userTempFolder,
28 
29 @"NewCreateDB.mdf");
30 
31 NewCreateDB newDB = newNewCreateDB(userMDF);
32 
33 if (newDB.DatabaseExists())
34 
35    Console.WriteLine("NewCreateDB數據庫存在");
36 
37 else
38 
39   Console.WriteLine("NewCreateDB數據庫不存在 ");
數據庫驗證
 1 數據庫更改
 2 
 3  
 4 
 5 SubmitChanges方法計算要插入、更 新或刪除的已修改對象的集,並執行相應命令以實現對數據庫的更改。
 6 
 7  
 8 
 9 無論對象做了多少項更改,都只是在更改內存中的副本。並未對數據庫中的實際數據做任何更改。直到對DataContext顯式調用SubmitChanges,所做的更改才會傳輸到服務器。調用時,DataContext會設法將我們所做的更改轉換為等效的SQL 命令。我們也可以使用自己的自定義邏輯來重寫這些操作,但提交順序是由 DataContext的一項稱作“更改處理器”的服務來協調的。事件的順序如下:
10 
11  
12 
13 當調用SubmitChanges時,LINQ to SQL會檢查已知對象的集合以確定新實例是否已附加到它們。如果已附加,這些新實例將添加到被跟蹤對象的集合。
14 
15  
16 
17 所有具有掛起更改的對象將按照它們之間的依賴關系排序成一個對象序列。如果一個對象的更改依賴於其他對象,則這個對象將排在其依賴項之后。
18 
19  
20 
21 在即將傳輸任何實際更改時,LINQ to SQL會啟動一個事務來封裝由各條命令組成的系列。
22 
23  
24 
25 對對象的更改會逐個轉換為SQL命令,然后發送到服務器。
26 
27  
28 
29 如果數據庫檢測到任何錯誤,都會造成提交進程停止並引發異常。將回滾對數據庫的所有更改,就像未進行過提交一樣。DataContext 仍具有所有更改的完整記錄。
30 
31  
32 
33 下面代碼說明的是在數據庫中查詢CustomerID 為ALFKI的顧客,然后修改其公司名稱,第一次更新並調用SubmitChanges()方法,第二次更新了數據但並未調用SubmitChanges()方法。
34 
35 //查詢
36 
37 Customer cust = db.Customers.First(c =>c.CustomerID == "ALFKI");
38 
39 //更新數據並調用SubmitChanges()方法
40 
41 cust.CompanyName = "YJingLee'sBlog";
42 
43 db.SubmitChanges();
44 
45 //更新數據沒有調用SubmitChanges()方法
46 
47 cust.CompanyName ="http://lyj.cnblogs.com";
數據庫更改
 1 動態查詢
 2 
 3  
 4 
 5 使用動態查詢,這個例子用CreateQuery()方法創建一個 IQueryable<T>類型表達式輸出查詢的語句。這里給個例子說明一下。有關動態查詢具體內容,下一篇介紹。
 6 
 7  
 8 
 9 var c1 =Expression.Parameter(typeof(Customer), "c");
10 
11 PropertyInfo City =typeof(Customer).GetProperty ("City");
12 
13 var pred =Expression.Lambda<Func<Customer, bool>>(
14 
15    Expression.Equal(
16 
17   Expression.Property(c1, City),
18 
19    Expression.Constant("Seattle")
20 
21   ), c1
22 
23 );
24 
25 IQueryable custs = db.Customers;
26 
27 Expression expr =Expression.Call(typeof(Queryable), "Where",
28 
29   new Type[] { custs.ElementType }, custs.Expression, pred);
30 
31 IQueryable<Customer> q =db.Customers.AsQueryable().
32 
33 Provider.CreateQuery<Customer>(expr);
動態查詢
 1 日志
 2 
 3  
 4 
 5 Log屬性用於將SQL查詢或命令打印到TextReader。此方法對了解 LINQto SQL 功能和調試特定的問題可能很有用。
 6 
 7  
 8 
 9 下面的示例使用Log屬性在 SQL代碼執行前在控制台窗口中顯示此代碼。我們可以將此屬性與查詢、插入、更新和刪除命令一起使用。
10 
11  
12 
13 //關閉日志功能
14 
15 //db.Log = null;
16 
17 //使用日志功能:日志輸出到控制台窗口
18 
19 db.Log = Console.Out;
20 
21 var q = from c in db.Customers
22 
23     where c.City == "London"
24 
25     select c;
26 
27 //日志輸出到 文件
28 
29 StreamWriter sw = newStreamWriter(Server.MapPath ("log.txt"), true);
30 
31 db.Log = sw;
32 
33 var q = from c in db.Customers
34 
35     where c.City == "London"
36 
37     select c;
38 
39 sw.Close();
日志

LINQ to SQL語句(23)之動態查詢

有這樣一個場景:應用程序可能會提供一個用戶界面,用戶可以使用該用戶界面指定一個或多個謂詞來篩選數據。這種情況在編譯時不知道查詢的細節,動態查詢將十分有用。

 

在LINQ中,Lambda表達式是許多標准查詢運算符的基礎,編譯器創建lambda表達式以捕獲基礎查詢方法(例如 Where、Select、Order By、Take While 以及其他方法)中定義的計算。表達式目錄樹用於針對數據源的結構化查詢,這些數據源實現IQueryable<T>。例如,LINQ to SQL 提供程序實現 IQueryable<T>接口,用於查詢關系數據存儲。C#和Visual Basic編譯器會針對此類數據源的查詢編譯為代碼,該代碼在運行時將生成一個表達式目錄樹。然后,查詢提供程序可以遍歷表達式目錄樹數據結構,並將其轉換為適合於數據源的查詢語言。

 

表達式目錄樹在 LINQ中用於表示分配給類型為Expression<TDelegate>的變量的Lambda表 達式。還可用於創建動態LINQ查詢。

 

System.Linq.Expressions命名空間 提供用於手動生成表達式目錄樹的API。Expression類包含創建特定類型的表達 式目錄樹節點的靜態工廠方法,例如,ParameterExpression(表示一個已命名的參數表達式)或 MethodCallExpression(表示一個方法調用)。編譯器生成的表達式目錄樹的根始終在類型Expression<TDelegate>的節點中,其中 TDelegate是包含至多五個輸入參數的任何TDelegate委托;也就是說,其根節點是表示一個lambda表達式。

 

下面幾個例子描述如何使用表達式目錄樹來創建動態LINQ查詢。

 1 1.Select
 2 
 3  
 4 
 5 下面例子說明如何使用表達式樹依據 IQueryable 數據源構造一個動態查詢,查詢出每個顧客的ContactName,並用GetCommand方法獲取其生成SQL語句。
 6 
 7  
 8 
 9 //依據IQueryable數據 源構造一個查詢
10 
11 IQueryable<Customer> custs =db.Customers;
12 
13 //組建一個表達式樹來創建一個參數
14 
15 ParameterExpression param =
16 
17   Expression.Parameter(typeof (Customer), "c");
18 
19 //組建表達式樹:c.ContactName
20 
21 Expression selector =Expression.Property(param,
22 
23   typeof (Customer).GetProperty("ContactName"));
24 
25 Expression pred =Expression.Lambda(selector, param);
26 
27 //組建表達式樹:Select(c=>c.ContactName)
28 
29 Expression expr = Expression.Call(typeof(Queryable), "Select",
30 
31   new Type[] { typeof (Customer), typeof(string) },
32 
33   Expression.Constant(custs), pred);
34 
35 //使用表達式樹來生成動態查詢
36 
37 IQueryable<string> query =db.Customers.AsQueryable()
38 
39   .Provider.CreateQuery<string>(expr);
40 
41 //使用GetCommand方法 獲取SQL語句
42 
43 System.Data.Common.DbCommand cmd =db.GetCommand (query);
44 
45 Console.WriteLine(cmd.CommandText);
46 
47  
48 
49 生成的 SQL語句為:
50 
51  
52 
53 SELECT [t0].[ContactName] FROM [dbo]. [Customers]AS [t0]
1.Select
  1 2.Where
  2 
  3  
  4 
  5 下面一個例子是“搭建”Where用法來動態查詢城市在倫敦的顧客。
  6 
  7  
  8 
  9 IQueryable<Customer> custs =db.Customers;
 10 
 11 // 創建一個參數c
 12 
 13 ParameterExpression param =
 14 
 15    Expression.Parameter(typeof(Customer), "c");
 16 
 17 //c.City=="London"
 18 
 19 Expression left = Expression.Property(param,
 20 
 21   typeof(Customer).GetProperty ("City"));
 22 
 23 Expression right = Expression.Constant("London");
 24 
 25 Expression filter = Expression.Equal(left,right);
 26 
 27 Expression pred = Expression.Lambda(filter,param);
 28 
 29 //Where(c=>c.City=="London")
 30 
 31 Expression expr = Expression.Call(typeof(Queryable),"Where",
 32 
 33   new Type[] { typeof(Customer) },
 34 
 35   Expression.Constant(custs), pred);
 36 
 37 //生成動態查詢
 38 
 39 IQueryable<Customer> query =db.Customers.AsQueryable()
 40 
 41   .Provider.CreateQuery<Customer>(expr);
 42 
 43  
 44 
 45 生成的SQL 語句為:
 46 
 47  
 48 
 49 SELECT [t0].[CustomerID],[t0].[CompanyName], [t0].[ContactName],
 50 
 51 [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region],
 52 
 53 [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
 54 
 55 FROM [dbo].[Customers] AS [t0] WHERE [t0].[City] = @p0
 56 
 57 -- @p0: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]
 58 
 59  
 60 
 61 3.OrderBy本例既實現排序功能又實現了過濾功能。
 62 
 63  
 64 
 65 IQueryable<Customer> custs =db.Customers;
 66 
 67 //創建一個 參數c
 68 
 69 ParameterExpression param =
 70 
 71   Expression.Parameter (typeof(Customer), "c");
 72 
 73 //c.City=="London"
 74 
 75 Expression left = Expression.Property(param,
 76 
 77    typeof(Customer).GetProperty ("City"));
 78 
 79 Expression right = Expression.Constant("London");
 80 
 81 Expression filter = Expression.Equal(left,right);
 82 
 83 Expression pred = Expression.Lambda(filter,param);
 84 
 85 //Where(c=>c.City=="London")
 86 
 87 MethodCallExpression whereCallExpression =Expression.Call(
 88 
 89    typeof(Queryable), "Where",
 90 
 91    new Type[] { typeof(Customer) },
 92 
 93    Expression.Constant(custs), pred);
 94 
 95 //OrderBy(ContactName => ContactName)
 96 
 97 MethodCallExpression orderByCallExpression= Expression.Call(
 98 
 99    typeof(Queryable), "OrderBy",
100 
101    new Type[] { typeof(Customer), typeof(string) },
102 
103    whereCallExpression,
104 
105    Expression.Lambda(Expression.Property
106 
107    (param, "ContactName"), param));
108 
109 //生成動態查詢
110 
111 IQueryable<Customer> query =db.Customers.AsQueryable()
112 
113    .Provider.CreateQuery<Customer> (orderByCallExpression);
114 
115  
116 
117 下面一張截圖顯示了怎么動態生成動態查詢的過程
118 
119  
120 
121 生成的SQL語句為:
122 
123  
124 
125 SELECT [t0].[CustomerID],[t0].[CompanyName], [t0].[ContactName],
126 
127 [t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region],
128 
129 [t0].[PostalCode], [t0].[Country], [t0].[Phone],[t0].[Fax]
130 
131 FROM [dbo].[Customers] AS [t0] WHERE[t0].[City] = @p0
132 
133 ORDER BY [t0].[ContactName]
134 
135 -- @p0: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]
136 
137 4.Union
138 
139  
140 
141 下面的例子使用表達式樹動態查詢顧客和雇員同在的城市。
142 
143  
144 
145 //e.City
146 
147 IQueryable<Customer> custs = db.Customers;     
148 
149 ParameterExpression param1 =
150 
151 Expression.Parameter(typeof(Customer),"e");
152 
153 Expression left1 =Expression.Property(param1,
154 
155   typeof (Customer).GetProperty("City"));
156 
157 Expression pred1 = Expression.Lambda(left1,param1);
158 
159 //c.City
160 
161 IQueryable<Employee> employees =db.Employees;
162 
163 ParameterExpression param2 =
164 
165 Expression.Parameter(typeof (Employee),"c");
166 
167 Expression left2 =Expression.Property(param2,
168 
169   typeof(Employee).GetProperty ("City"));
170 
171 Expression pred2 = Expression.Lambda(left2,param2);
172 
173 //Select(e=>e.City)
174 
175 Expression expr1 =Expression.Call(typeof(Queryable), "Select",
176 
177   new Type[] { typeof(Customer), typeof(string) },
178 
179    Expression.Constant(custs), pred1);
180 
181 //Select(c=>c.City)
182 
183 Expression expr2 =Expression.Call(typeof(Queryable), "Select",
184 
185   new Type[] { typeof(Employee), typeof (string) },
186 
187   Expression.Constant(employees), pred2);
188 
189 //生 成動態查詢
190 
191 IQueryable<string> q1 =db.Customers.AsQueryable()
192 
193   .Provider.CreateQuery<string>(expr1);
194 
195 IQueryable<string> q2 =db.Employees.AsQueryable()
196 
197   .Provider.CreateQuery<string>(expr2);
198 
199 //並集
200 
201 var q3 = q1.Union(q2);
202 
203  
204 
205 生成的SQL語句為:
206 
207  
208 
209 SELECT [t2].[City]
210 
211 FROM (
212 
213   SELECT [t0].[City] FROM [dbo]. [Customers] AS [t0]
214 
215   UNION
216 
217   SELECT [t1].[City] FROM [dbo].[Employees] AS [t1]
218 
219   ) AS [t2]
2.Where

LINQ to SQL語句(24)之視圖

視圖

 

我們使用視圖和使用數據表類似,只需將視圖從“服務器資源管理器/數據庫資源管理器”拖動到O/R 設計器上,自動可以創建基於這些視圖的實體類。我們可以同操作數據表一樣來操作視圖了。這里注意:O/R 設計器是一個簡單的對象關系映射器,因為它僅支持 1:1 映射關系。換句話說,實體類與數據庫表或視圖之間只能具有 1:1 映射關系。不支持復雜映射(例如,將一個實體類映射到多個表)。但是,可以將一個實體類映射到一個聯接多個相關表的視圖。 下面使用NORTHWND數據庫中自帶的Invoices、QuarterlyOrders 兩個視圖為例,寫出兩個范例。

 1 查詢:匿名類型形式
 2 
 3  
 4 
 5 我們使用下面代碼來查詢出ShipCity 在London的發票。
 6 
 7  
 8 
 9 var q =
10 
11   from i in db.Invoices
12 
13   where i.ShipCity == "London"
14 
15   select new
16 
17   {
18 
19     i.OrderID,
20 
21      i.ProductName,
22 
23     i.Quantity,
24 
25     i.CustomerName
26 
27   };
28 
29  
30 
31 這里,生成的SQL語句同使用數據表類似:
32 
33  
34 
35 SELECT [t0].[OrderID], [t0].[ProductName],[t0]. [Quantity],
36 
37 [t0].[CustomerName] FROM [dbo].[Invoices]AS [t0]
38 
39 WHERE [t0].[ShipCity] = @p0
40 
41 -- @p0: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]
查詢:匿名類型形式
 1 查詢:標識映射形式
 2 
 3  
 4 
 5 下例查詢出每季的訂單。
 6 
 7  
 8 
 9 var q =
10 
11   from qo in db.Quarterly_Orders
12 
13   select qo;
14 
15  
16 
17 生成SQL語句為:
18 
19  
20 
21 SELECT [t0].[CustomerID],[t0].[CompanyName], [t0]. [City],
22 
23 [t0].[Country] FROM [dbo].[QuarterlyOrders] AS [t0]
查詢:標識映射形式

LINQ to SQL語句(25)之繼承

 1 繼承支持
 2 
 3  
 4 
 5 LINQ to SQL 支持單表映射,其整個繼承層次結構存儲在單個數據庫表中。該表包含整個層次結構的所有可能數據列的平展聯合。(聯合是將兩個表組合成一個表的結果,組合后的表包含任一原始表中存在的行。)每行中不適用於該行所表示的實例類型的列為 null 6 
 7  
 8 
 9 單表映射策略是最簡單的繼承表示形式,為許多不同類別的查詢提供了良好的性能特征,如果我們要在 LINQ to SQL 中實現這種映射,必須在繼承層次結構的根類中指定屬性 (Attribute) 和屬性 (Attribute) 的屬性 (Property)。我們還可以使用O/R設計器來映射繼承層次結構,它自動生成了代碼。
10 
11  
12 
13 下面為了演示下面的幾個例子,我們在O/R設計器內設計如下圖所示的類及其繼承關系。
14 
15  
16 
17 我們學習的時候還是看看其生成的代碼吧!
18 
19  
20 
21 具體設置映射繼承層次結構有如下幾步:
22 
23  
24 
25 根類添加TableAttribute屬性。
26 
27  
28 
29 為層次結構中的每個類添加InheritanceMappingAttribute屬性,同樣是添加到根類中。每個InheritanceMappingAttribute屬性,定義一個Code屬性和一個Type屬性。Code 屬性的值顯示在數據庫表的IsDiscriminator列中,用來指示該行數據所屬的類或子類。Type屬性值指定鍵值所表示的類或子類。
30 
31  
32 
33 僅在其中一個 InheritanceMappingAttribute屬性上,添加一個IsDefault屬性用來在數據庫表 中的鑒別器值在繼承映射中不與任何Code值匹配時指定回退映射。
34 
35  
36 
37 為 ColumnAttribute屬性添加一個IsDiscriminator屬性來表示這是保存Code值的列。
38 
39  
40 
41 下面是這張圖生成的代碼的框架(由於生成的代碼太多,我刪除了很多“枝葉”,僅僅保留了主要的框架用於指出其實質的東西):
42 
43  
44 
45 [Table(Name = "dbo.Contacts")]
46 
47 [InheritanceMapping(Code ="Unknown", Type = typeof (Contact),
48 
49           IsDefault = true)]
50 
51 [InheritanceMapping(Code ="Employee", Type = typeof (EmployeeContact))]
52 
53 [InheritanceMapping(Code ="Supplier", Type = typeof(SupplierContact))]
54 
55 [InheritanceMapping(Code ="Customer", Type = typeof (CustomerContact))]
56 
57 [InheritanceMapping(Code ="Shipper", Type = typeof(ShipperContact))]
58 
59 public partial class Contact :
60 
61 INotifyPropertyChanging,INotifyPropertyChanged
62 
63 {
64 
65   [Column(Storage = "_ContactID",IsPrimaryKey = true,
66 
67   IsDbGenerated = true)]
68 
69   public int ContactID{ }
70 
71   [Column(Storage = "_ContactType",IsDiscriminator = true)]
72 
73   public string ContactType{ }
74 
75 }
76 
77 public abstract partial class FullContact :Contact{ }
78 
79 public partial class EmployeeContact :FullContact{ }
80 
81 public partial class SupplierContact :FullContact{ }
82 
83 public partial class CustomerContact :FullContact{ }
84 
85 public partial class ShipperContact :Contact{ }
繼承支持(概念,代碼框架)
 1 1.一般形式
 2 
 3  
 4 
 5 日常我們經常寫的形式,對單表查詢。
 6 
 7  
 8 
 9 var cons = from c in db.Contacts
10 
11       select c;
12 
13 foreach (var con in cons) {
14 
15    Console.WriteLine("Company name: {0}", con.CompanyName);
16 
17   Console.WriteLine("Phone: {0}", con.Phone);
18 
19    Console.WriteLine("This is a {0}", con.GetType());
20 
21 }
1.一般形式
 1 2.OfType形式
 2 
 3  
 4 
 5 這里我僅僅讓其返回顧客的聯系方式。
 6 
 7  
 8 
 9 var cons = from c indb.Contacts.OfType<CustomerContact>()
10 
11       select c;
12 
13  
14 
15 初步學習,我們還是看看生成的SQL語句,這樣容易理解。在 SQL語句中查詢了ContactType為Customer的聯系方式。
16 
17  
18 
19 SELECT [t0].[ContactType],[t0].[ContactName], [t0].[ContactTitle],
20 
21 [t0].[Address],[t0].[City], [t0].[Region],[t0].[PostalCode],
22 
23 [t0].[Country],[t0].[Fax],[t0].[ContactID], [t0].[CompanyName],
24 
25 [t0].[Phone] FROM [dbo].[Contacts] AS [t0]
26 
27 WHERE ([t0]. [ContactType] = @p0) AND([t0].[ContactType] IS NOT NULL)
28 
29 -- @p0: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Customer]
2.OfType形式
 1 3.IS形式
 2 
 3  
 4 
 5 這個例子查找一下發貨人的聯系方式。
 6 
 7  
 8 
 9 var cons = from c in db.Contacts
10 
11       where c is ShipperContact
12 
13       select c;
14 
15  
16 
17 生成的SQL語句如下:查詢了ContactType為Shipper的聯系方式。大致一看好像很上面的一樣,其實這里查詢出來的列多了很多。實際上是Contacts表的全部字段。
18 
19  
20 
21 SELECT [t0].[ContactType],[t0].[ContactID], [t0]. [CompanyName],
22 
23 [t0].[Phone],[t0].[HomePage], [t0].[ContactName],
24 
25 [t0].[ContactTitle], [t0].[Address], [t0].[City],
26 
27 [t0].[Region], [t0].[PostalCode],[t0].[Country],
28 
29 [t0].[Fax],[t0].[PhotoPath], [t0].[Photo],[t0].[Extension]
30 
31 FROM [dbo].[Contacts] AS [t0] WHERE([t0].[ContactType] = @p0)
32 
33 AND ([t0].[ContactType] IS NOT NULL)
34 
35 -- @p0: Input NVarChar (Size = 7; Prec = 0;Scale = 0) [Shipper]
3.IS形式
 1 4.AS形式
 2 
 3  
 4 
 5 這個例子就通吃了,全部查找了一番。
 6 
 7  
 8 
 9 var cons = from c in db.Contacts
10 
11       select c as FullContact;
12 
13  
14 
15 生成 SQL語句如下:查詢整個Contacts表。
16 
17  
18 
19 SELECT [t0]. [ContactType],[t0].[HomePage], [t0].[ContactName],
20 
21 [t0]. [ContactTitle],[t0].[Address],[t0].[City],
22 
23 [t0].[Region], [t0]. [PostalCode],[t0].[Country],
24 
25 [t0].[Fax], [t0].[ContactID],[t0].[CompanyName],
26 
27 [t0].[Phone],[t0].[PhotoPath],[t0].[Photo], [t0].[Extension]
28 
29 FROM [dbo].[Contacts] AS [t0]
4.AS形式
 1 5.Cast形式
 2 
 3  
 4 
 5 使用Case形式查找出在倫敦的顧客的聯系方式。
 6 
 7  
 8 
 9 var cons = from c in db.Contacts
10 
11       where c.ContactType == "Customer" &&
12 
13            ((CustomerContact)c).City == "London"
14 
15       select c;
16 
17  
18 
19 生成SQL語句如下,自己可以看懂了。
20 
21  
22 
23 SELECT [t0].[ContactType],[t0].[ContactID], [t0]. [CompanyName],
24 
25 [t0].[Phone], [t0].[HomePage],[t0].[ContactName],
26 
27 [t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region],
28 
29 [t0].[PostalCode], [t0].[Country],[t0].[Fax], [t0].[PhotoPath],
30 
31 [t0].[Photo], [t0].[Extension]FROM [dbo].[Contacts] AS [t0]
32 
33 WHERE ([t0].[ContactType] = @p0) AND ([t0].[City] = @p1)
34 
35 -- @p0: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Customer]
36 
37 -- @p1: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]
5.Cast形式
 1 6.UseAsDefault形式
 2 
 3  
 4 
 5 當插入一條記錄時,使用默認的映射關系了,但是在查詢時,使用繼承的關系了。具體看看生成的SQL 語句就直截了當了。
 6 
 7  
 8 
 9 //插入一條數據默認使用正常的映射關系
10 
11 Contact contact = new Contact()
12 
13 {
14 
15   ContactType = null,
16 
17   CompanyName = "Unknown Company",
18 
19    Phone = "333-444-5555"
20 
21 };
22 
23 db.Contacts.InsertOnSubmit(contact);
24 
25 db.SubmitChanges();
26 
27 //查詢一條數據默認使用繼承映射關系
28 
29 var con =
30 
31   (from c in db.Contacts
32 
33    where c.CompanyName == "Unknown Company" &&
34 
35               c.Phone == "333-444-5555"
36 
37    select c).First();
38 
39  
40 
41 生成SQL語句如下:
42 
43  
44 
45 INSERT INTO [dbo].[Contacts]([ContactType], [CompanyName],
46 
47 [Phone]) VALUES (@p0, @p1, @p2)
48 
49 SELECT TOP (1) [t0].[ContactType], [t0].[ContactID],
50 
51 [t0]. [CompanyName],[t0].[Phone],[t0].[HomePage],
52 
53 [t0].[ContactName], [t0].[ContactTitle],[t0].[Address],
54 
55 [t0].[City],[t0].[Region],[t0].[PostalCode], [t0].[Country],
56 
57 [t0].[Fax], [t0].[PhotoPath], [t0].[Photo],[t0].[Extension]
58 
59 FROM [dbo].[Contacts] AS [t0]
60 
61 WHERE ([t0].[CompanyName] = @p0) AND([t0].[Phone] = @p1)
62 
63 -- @p0: Input NVarChar (Size = 15; Prec =0; Scale = 0)
64 
65   [Unknown Company]
66 
67 -- @p1: Input NVarChar (Size = 12; Prec =0; Scale = 0)
68 
69   [333-444-5555]
6.UseAsDefault形式
  1 7.插入新的記錄
  2 
  3  
  4 
  5 這個例子說明如何插入發貨人的聯系方式的一條記錄。
  6 
  7  
  8 
  9 //
 10 
 11  
 12 
 13 1.在插入之前查詢一下,沒有數據
 14 
 15 var ShipperContacts =
 16 
 17   from sc in db.Contacts.OfType<ShipperContact>()
 18 
 19   where sc.CompanyName == "Northwind Shipper"
 20 
 21   select sc;
 22 
 23 //
 24 
 25  
 26 
 27 2.插入數據
 28 
 29 ShipperContact nsc = new ShipperContact()
 30 
 31 {
 32 
 33   CompanyName = "Northwind Shipper",
 34 
 35   Phone = "(123)-456-7890"
 36 
 37 };
 38 
 39 db.Contacts.InsertOnSubmit(nsc);
 40 
 41 db.SubmitChanges();
 42 
 43 //
 44 
 45  
 46 
 47 3.查詢數據,有一條記錄
 48 
 49 ShipperContacts =
 50 
 51   from sc in db.Contacts.OfType<ShipperContact>()
 52 
 53    where sc.CompanyName == "Northwind Shipper"
 54 
 55   select sc;
 56 
 57 //
 58 
 59  
 60 
 61 4.刪除記錄
 62 
 63 db.Contacts.DeleteOnSubmit (nsc);
 64 
 65 db.SubmitChanges();
 66 
 67  
 68 
 69 生成SQL語句如下:
 70 
 71  
 72 
 73 SELECT COUNT(*) AS [value] FROM[dbo].[Contacts] AS [t0]
 74 
 75 WHERE ([t0].[CompanyName] = @p0) AND([t0].[ContactType] = @p1)
 76 
 77 AND ([t0].[ContactType] IS NOT NULL)
 78 
 79 -- @p0: Input NVarChar [Northwind Shipper]
 80 
 81 -- @p1: Input NVarChar [Shipper]
 82 
 83 INSERT INTO [dbo].[Contacts]([ContactType],[CompanyName], [Phone])
 84 
 85 VALUES (@p0, @p1, @p2)
 86 
 87 -- @p0: Input NVarChar [Shipper]
 88 
 89 -- @p1: Input NVarChar [NorthwindShipper]
 90 
 91 -- @p2: Input NVarChar [(123)-456-7890]
 92 
 93 SELECT COUNT(*) AS [value] FROM[dbo].[Contacts] AS [t0]
 94 
 95 WHERE ([t0].[CompanyName] = @p0) AND([t0].[ContactType] = @p1)
 96 
 97 AND ([t0].[ContactType] IS NOT NULL)
 98 
 99 -- @p0: Input NVarChar [Northwind Shipper]
100 
101 -- @p1: Input NVarChar [Shipper]
102 
103 DELETE FROM [dbo].[Contacts] WHERE ([ContactID]= @p0) AND
104 
105 ([ContactType] = @p1) AND ([CompanyName] =@p2) AND ([Phone] = @p3)
106 
107 -- @p0: Input Int [159]
108 
109 -- @p1: Input NVarChar [Shipper]
110 
111 -- @p2: Input NVarChar [NorthwindShipper]
112 
113 -- @p3: Input NVarChar [(123)-456-7890]
114 
115 -- @p4: Input NVarChar [Unknown]
116 
117 -- @p5: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Supplier]
118 
119 -- @p6: Input NVarChar (Size = 7; Prec = 0;Scale = 0) [Shipper]
120 
121 -- @p7: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Employee]
122 
123 -- @p8: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Customer]
7.插入新的記錄

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM