8d8c325cbec773aba06c7b293d75553ace8c292b
[mono.git] / mcs / class / System.Data.Linq / src / DbLinq / Test / Providers / ReadTest_Complex.cs
1 #region MIT license\r
2 // \r
3 // MIT license\r
4 //\r
5 // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne\r
6 // \r
7 // Permission is hereby granted, free of charge, to any person obtaining a copy\r
8 // of this software and associated documentation files (the "Software"), to deal\r
9 // in the Software without restriction, including without limitation the rights\r
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
11 // copies of the Software, and to permit persons to whom the Software is\r
12 // furnished to do so, subject to the following conditions:\r
13 // \r
14 // The above copyright notice and this permission notice shall be included in\r
15 // all copies or substantial portions of the Software.\r
16 // \r
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
23 // THE SOFTWARE.\r
24 // \r
25 #endregion\r
26 using System;\r
27 using System.Collections.Generic;\r
28 using System.Data.Linq;\r
29 using System.Text;\r
30 using System.Linq;\r
31 using System.Linq.Expressions;\r
32 using NUnit.Framework;\r
33 using Test_NUnit;\r
34 \r
35 using nwind;\r
36 \r
37 #if ORACLE\r
38 using Id = System.Decimal;\r
39 #else\r
40 using Id = System.Int32;\r
41 #endif\r
42 \r
43 // test ns \r
44 #if MYSQL\r
45     namespace Test_NUnit_MySql\r
46 #elif ORACLE && ODP\r
47     namespace Test_NUnit_OracleODP\r
48 #elif ORACLE\r
49     namespace Test_NUnit_Oracle\r
50 #elif POSTGRES\r
51     namespace Test_NUnit_PostgreSql\r
52 #elif SQLITE\r
53     namespace Test_NUnit_Sqlite\r
54 #elif INGRES\r
55     namespace Test_NUnit_Ingres\r
56 #elif MSSQL && L2SQL\r
57     namespace Test_NUnit_MsSql_Strict\r
58 #elif MSSQL\r
59     namespace Test_NUnit_MsSql\r
60 #elif FIREBIRD\r
61     namespace Test_NUnit_Firebird\r
62 #endif\r
63 {\r
64     [TestFixture]\r
65     public class ReadTest_Complex : TestBase\r
66     {\r
67         Northwind db;\r
68 \r
69         public ReadTest_Complex()\r
70         {\r
71             db = CreateDB();\r
72 \r
73         }\r
74 \r
75         #region 'D' tests exercise 'local object constants'\r
76         [Test]\r
77         public void D0_SelectPensByLocalProperty()\r
78         {\r
79             //reported by Andrus.\r
80             //http://groups.google.com/group/dblinq/browse_thread/thread/c25527cbed93d265\r
81 \r
82             Northwind db = CreateDB();\r
83 \r
84             Product localProduct = new Product { ProductName = "Chai" };\r
85             var q = from p in db.Products where p.ProductName == localProduct.ProductName select p;\r
86 \r
87             List<Product> products = q.ToList();\r
88             int productCount = products.Count;\r
89             Assert.AreEqual(productCount, 1, "Expected one pen, got count=" + productCount);\r
90         }\r
91 \r
92         [Test]\r
93         public void D1_SelectPensByLocalProperty()\r
94         {\r
95             Northwind db = CreateDB();\r
96             var pen = new { Name = "Chai" };\r
97             var q = from p in db.Products where p.ProductName == pen.Name select p;\r
98 \r
99             List<Product> products = q.ToList();\r
100             int productCount = products.Count;\r
101             Assert.AreEqual(productCount, 1, "Expected one pen, got count=" + productCount);\r
102         }\r
103 \r
104         [Test]\r
105         public void D2_SelectProductByLocalPropertyAndConstant()\r
106         {\r
107 \r
108             Northwind db = CreateDB();\r
109             string product = "Carnarvon Tigers";\r
110             var q = from p in db.Products\r
111                     where p.ProductName == product &&\r
112                         p.QuantityPerUnit.StartsWith("16")\r
113                     select p;\r
114             List<Product> products = q.ToList();\r
115             int productCount = products.Count;\r
116             Assert.AreEqual(1, productCount, "Expected one product, got count=" + productCount);\r
117         }\r
118 \r
119         [Test]\r
120         public void D3_ArrayContains()\r
121         {\r
122             Northwind db = CreateDB();\r
123 \r
124             var data = from p in db.Customers\r
125                        where new string[] { "ALFKI", "WARTH" }.Contains(p.CustomerID)\r
126                        select new { p.CustomerID, p.Country };\r
127 \r
128             var dataList = data.ToList();\r
129             //Assert.AreEqual(productCount, 1, "Expected one pen, got count=" + productCount);\r
130         }\r
131         #endregion\r
132 \r
133         #region Tests 'F' work on aggregation\r
134         [Test]\r
135         public void F1_ProductCount()\r
136         {\r
137             var q = from p in db.Products select p;\r
138             int productCount = q.Count();\r
139             Assert.Greater(productCount, 0, "Expected non-zero product count");\r
140         }\r
141 \r
142         [Test]\r
143         public void F2_ProductCount_Projected()\r
144         {\r
145             var q = from p in db.Products select p.ProductID;\r
146             int productCount = q.Count();\r
147             Assert.Greater(productCount, 0, "Expected non-zero product count");\r
148             Console.WriteLine();\r
149         }\r
150         [Test]\r
151         public void F2_ProductCount_Clause()\r
152         {\r
153             var q = from p in db.Products select p.ProductID;\r
154             int productCount = q.Count(i => i < 3);\r
155             Assert.Greater(productCount, 0, "Expected non-zero product count");\r
156             Assert.IsTrue(productCount < 4, "Expected product count < 3");\r
157         }\r
158 \r
159         [Test]\r
160         public void F3_MaxProductId()\r
161         {\r
162             var q = from p in db.Products select p.ProductID;\r
163             var maxID = q.Max();\r
164             Assert.Greater(maxID, 0, "Expected non-zero product count");\r
165         }\r
166 \r
167         [Test]\r
168         public void F4_MinProductId()\r
169         {\r
170             var q = from p in db.Products select p.ProductID;\r
171             var minID = q.Min();\r
172             Assert.Greater(minID, 0, "Expected non-zero product count");\r
173         }\r
174 \r
175 #if !ORACLE // picrap: this test causes an internal buffer overflow when marshaling with oracle win32 driver\r
176 \r
177         [Test]\r
178         public void F5_AvgProductId()\r
179         {\r
180             var q = from p in db.Products select p.ProductID;\r
181             double avg = q.Average();\r
182             Assert.Greater(avg, 0, "Expected non-zero productID average");\r
183         }\r
184 \r
185 #endif\r
186 \r
187         [Test]\r
188         public void F7_ExplicitJoin()\r
189         {\r
190             //a nice and light nonsense join:\r
191             //bring in rows such as {Chai,AIRBU}\r
192             var q =\r
193                 from p in db.Products\r
194                 join c in db.Categories on p.ProductID equals c.CategoryID\r
195                 select new { p.ProductName, c.CategoryName };\r
196 \r
197             int rowCount = 0;\r
198             foreach (var v in q)\r
199             {\r
200                 rowCount++;\r
201                 Assert.IsTrue(v.ProductName != null);\r
202                 Assert.IsTrue(v.CategoryName != null);\r
203             }\r
204             Assert.IsTrue(rowCount > 2);\r
205         }\r
206 \r
207         [Test]\r
208         public void F7b_ExplicitJoin()\r
209         {\r
210             var q =\r
211                 from c in db.Customers\r
212                 join o in db.Orders on c.CustomerID equals o.CustomerID\r
213                 where c.City == "London"\r
214                 select o;\r
215         }\r
216 \r
217 #if INCLUDING_CLAUSE\r
218         //Including() clause discontinued in Studio Orcas?\r
219         [Test]\r
220         public void F8_IncludingClause()\r
221         {\r
222             var q = (\r
223                     from c in db.Customers\r
224                     where c.City == "London"\r
225                     select c)\r
226                     .Including(c => c.Orders);\r
227         }\r
228 \r
229         [Test]\r
230         public void F8_Including_Nested()\r
231         {\r
232             var q = (\r
233                     from c in db.Customers\r
234                     where c.City == "London"\r
235                     select c)\r
236                     .Including(c => c.Orders.Including(o => o.OrderDetails));\r
237         }\r
238 #endif\r
239 \r
240         [Test]\r
241         public void F9_Project_AndContinue()\r
242         {\r
243             var q =\r
244                 from c in db.Customers\r
245                 where c.City == "London"\r
246                 select new { Name = c.ContactName, c.Phone } into x\r
247                 orderby x.Name\r
248                 select x;\r
249         }\r
250 \r
251         [Test]\r
252         public void F10_DistinctCity()\r
253         {\r
254             var q1 = from c in db.Customers select c.City;\r
255             var q2 = q1.Distinct();\r
256 \r
257             int numLondon = 0;\r
258             foreach (string city in q2)\r
259             {\r
260                 if (city == "London") { numLondon++; }\r
261             }\r
262             Assert.AreEqual(1, numLondon, "Expected to see London once");\r
263         }\r
264 \r
265         [Test]\r
266         public void F11_ConcatString()\r
267         {\r
268             var q4 = from p in db.Products select p.ProductName + p.ProductID;\r
269             //var q4 = from p in db.Products select p.ProductID;\r
270             var q5 = q4.ToList();\r
271             Assert.Greater(q5.Count, 2, "Expected to see some concat strings");\r
272             foreach (string s0 in q5)\r
273             {\r
274                 bool startWithLetter = Char.IsLetter(s0[0]);\r
275                 bool endsWithDigit = Char.IsDigit(s0[s0.Length - 1]);\r
276                 Assert.IsTrue(startWithLetter && endsWithDigit, "String must start with letter and end with digit");\r
277             }\r
278         }\r
279 \r
280 #if !DEBUG && POSTGRES\r
281         [Explicit]\r
282 #endif\r
283         [Test]\r
284         public void F12_ConcatString_2()\r
285         {\r
286             var q4 = from p in db.Products\r
287                      where (p.ProductName + p.ProductID).Contains("e")\r
288                      select p.ProductName+p.ProductID;\r
289             //var q4 = from p in db.Products select p.ProductID;\r
290             //var q5 = q4.ToList();\r
291             Assert.Greater( q4.Count(), 2, "Expected to see some concat strings");\r
292             foreach(string s0 in q4)\r
293             {\r
294                 bool startWithLetter = Char.IsLetter(s0[0]);\r
295                 bool endsWithDigit = Char.IsDigit(s0[s0.Length-1]);\r
296                 Assert.IsTrue(startWithLetter && endsWithDigit, "String must start with letter and end with digit");\r
297             }\r
298         }\r
299         #endregion\r
300 \r
301         const string obsoleteError = @"Since beta2 in Linq2Sql to project a new entity (ie: select new Order(3)) is forbidden for coherence reasons, so this tests doesn't mimic the Linq2Sql behavior and it is obsolete and should be modified. If you apply such test cases to Linq2Sql you'll get Test_NUnit_MsSql_Strict.DynamicLinqTest.DL5_NestedObjectSelect:\r
302         System.NotSupportedException : Explicit construction of entity type 'MsNorthwind.XX' in query is not allowed.\n\nMore Info in: http://linqinaction.net/blogs/roller/archive/2007/11/27/explicit-construction-of-entity-type-in-query-is-not-allowed.aspx";\r
303         [Test]\r
304         public void F13_NewCustomer()\r
305         {\r
306             Assert.Ignore(obsoleteError);\r
307             Northwind db = CreateDB();\r
308             IQueryable<Customer> q = (from c in db.Customers\r
309                                       select\r
310                                       new Customer\r
311                                       {\r
312                                           CustomerID = c.CustomerID\r
313                                       });\r
314             var list = q.ToList();\r
315             Assert.Greater(list.Count(), 0, "Expected list");\r
316             //Assert.Greater(list.Count(), 0, "Expected list");\r
317             Assert.Ignore("test passed but: theoretically constructions of entity types are not allowed");\r
318         }\r
319 \r
320         [Test]\r
321         public void F14_NewCustomer_Order()\r
322         {\r
323             Assert.Ignore(obsoleteError);\r
324             Northwind db = CreateDB();\r
325             IQueryable<Customer> q = (from c in db.Customers\r
326                                       select\r
327                                       new Customer\r
328                                       {\r
329                                           CustomerID = c.CustomerID\r
330                                       });\r
331             //this OrderBy clause messes up the SQL statement\r
332             var q2 = q.OrderBy(c => c.CustomerID);\r
333             var list = q2.ToList();\r
334             Assert.Greater(list.Count(), 0, "Expected list");\r
335             //Assert.Greater(list.Count(), 0, "Expected list");\r
336         }\r
337 \r
338 \r
339         [Test]\r
340         public void F15_OrderByCoalesce()\r
341         {\r
342             Northwind db = CreateDB();\r
343             var q = from c in db.Customers\r
344                     orderby c.ContactName ?? ""\r
345                     select c;\r
346             var list = q.ToList();\r
347             Assert.Greater(list.Count(), 0, "Expected list");\r
348         }\r
349 \r
350         [Test(Description = "Non-dynamic version of DL5_NestedObjectSelect")]\r
351         public void F16_NestedObjectSelect()\r
352         {\r
353             Assert.Ignore(obsoleteError);\r
354             Northwind db = CreateDB();\r
355             var q = from o in db.Orders\r
356                     select new Order() { OrderID = o.OrderID, Customer = new Customer() { ContactName = o.Customer.ContactName } };\r
357             var list = q.ToList();\r
358         }\r
359 \r
360         [Test(Description = "Non-dynamic version of DL5_NestedObjectSelect")]\r
361         public void F17_NestedObjectSelect_Ver2()\r
362         {\r
363             Assert.Ignore(obsoleteError);\r
364             Northwind db = CreateDB();\r
365             var query = from order in db.Orders\r
366                         select new Order\r
367                         {\r
368                             OrderID = order.OrderID,\r
369                             Customer = new Customer\r
370                             {\r
371                                 ContactName = order.Customer.ContactName,\r
372                                 ContactTitle = order.Customer.ContactTitle\r
373                             }\r
374                         };\r
375             var list = query.ToList();\r
376             Assert.IsTrue(list.Count > 0);\r
377         }\r
378 \r
379 #if !DEBUG && POSTGRES\r
380         [Explicit]\r
381 #endif\r
382         [Test(Description = "byte[] test")]\r
383         public void F18_ByteArrayAssignmentTest()\r
384         {\r
385             var db = CreateDB();\r
386 \r
387             var picture = new byte[] { 1, 2, 3, 4 };\r
388 \r
389             var nc = new Category { CategoryName = "test", Picture = picture };\r
390             db.Categories.InsertOnSubmit(nc);\r
391             db.SubmitChanges();\r
392 \r
393             var q = from c in db.Categories \r
394                     where c.CategoryName == "test"\r
395                     select new { c.Picture };\r
396             var l = q.ToList();\r
397             Assert.IsTrue(l.Count > 0);\r
398             Assert.IsTrue(picture.SequenceEqual(l[0].Picture.ToArray()));\r
399 \r
400             db.Categories.DeleteOnSubmit(nc);\r
401             db.SubmitChanges();\r
402         }\r
403 \r
404 \r
405         [Test]\r
406         public void F19_ExceptWithCount_ViaToList()\r
407         {\r
408             var db = CreateDB();\r
409 \r
410             var toExclude = from t in db.GetTable<Territory>()\r
411                             where t.TerritoryDescription.StartsWith("A")\r
412                             select t;\r
413             var universe = from t in db.GetTable<Territory>() select t;\r
414             var toTake = universe.Except(toExclude);\r
415             \r
416             int toListCount = toTake.ToList().Count;\r
417             Assert.AreEqual(51, toListCount);\r
418         }\r
419 \r
420         [Test]\r
421         public void F20_ExceptWithCount()\r
422         {\r
423             var db = CreateDB();\r
424 \r
425             var toExclude = from t in db.GetTable<Territory>()\r
426                             where t.TerritoryDescription.StartsWith("A")\r
427                             select t;\r
428             var universe = from t in db.GetTable<Territory>() select t;\r
429             var toTake = universe.Except(toExclude).Except(db.Territories.Where(terr => terr.TerritoryDescription.StartsWith("B")));\r
430 \r
431             int toTakeCount = toTake.Count();\r
432             Assert.AreEqual(44, toTakeCount);\r
433         }\r
434 \r
435 #if !DEBUG && (SQLITE)\r
436         [Explicit]\r
437 #endif\r
438         [Test]\r
439         public void F21_CountNestedExcepts()\r
440         {\r
441             var db = CreateDB();\r
442 \r
443             var toExclude1 = from t in db.GetTable<Territory>()\r
444                             where t.TerritoryDescription.StartsWith("A")\r
445                             select t;\r
446             var toExclude2 = toExclude1.Except(db.GetTable<Territory>().Where(terr => terr.TerritoryDescription.Contains("i")));\r
447 \r
448             var universe = from t in db.GetTable<Territory>() select t;\r
449 \r
450             var toTake = universe.Except(toExclude2);\r
451 \r
452             int toTakeCount = toTake.Count();\r
453             Assert.AreEqual(52, toTakeCount);\r
454         }\r
455 \r
456 #if !DEBUG && (SQLITE)\r
457         [Explicit]\r
458 #endif\r
459         [Test]\r
460         public void F22_AnyNestedExcepts()\r
461         {\r
462             var db = CreateDB();\r
463 \r
464             var toExclude1 = from t in db.GetTable<Territory>()\r
465                              where t.TerritoryDescription.StartsWith("A")\r
466                              select t;\r
467             var toExclude2 = toExclude1.Except(db.GetTable<Territory>().Where(terr => terr.TerritoryDescription.Contains("i")));\r
468 \r
469             var universe = from t in db.GetTable<Territory>() select t;\r
470 \r
471             var toTake = universe.Except(toExclude2);\r
472 \r
473             Assert.IsTrue(toTake.Any());\r
474         }\r
475 \r
476 #if !DEBUG && SQLITE\r
477         [Explicit]\r
478 #endif\r
479         [Test]\r
480         public void F23_AnyNestedExcepts_WithParameter()\r
481         {\r
482             var db = CreateDB();\r
483 \r
484             var toExclude1 = from t in db.GetTable<Territory>()\r
485                              where t.TerritoryDescription.StartsWith("A")\r
486                              select t;\r
487             var toExclude2 = toExclude1.Except(db.GetTable<Territory>().Where(terr => terr.TerritoryDescription.Contains("i")));\r
488 \r
489             var universe = from t in db.GetTable<Territory>() select t;\r
490 \r
491             var toTake = universe.Except(toExclude2);\r
492 \r
493             Assert.IsTrue(toTake.Any(t => t.TerritoryDescription.Contains("i")));\r
494         }\r
495 \r
496 #if !DEBUG && SQLITE\r
497         [Explicit]\r
498 #endif\r
499         [Test]\r
500         public void F24_CountNestedExcepts_WithParameter()\r
501         {\r
502             var db = CreateDB();\r
503 \r
504             var toExclude1 = from t in db.GetTable<Territory>()\r
505                              where t.TerritoryDescription.StartsWith("A")\r
506                              select t;\r
507             var toExclude2 = toExclude1.Except(db.GetTable<Territory>().Where(terr => terr.TerritoryDescription.Contains("i")));\r
508 \r
509             var universe = from t in db.GetTable<Territory>() select t;\r
510 \r
511             var toTake = universe.Except(toExclude2);\r
512 \r
513             int toTakeCount = toTake.Count(t => t.TerritoryDescription.Contains("o"));\r
514             Assert.AreEqual(34, toTakeCount);\r
515         }\r
516 \r
517         [Test]\r
518         public void F25_DistinctUnion()\r
519         {\r
520             var db = CreateDB();\r
521 \r
522             var toInclude1 = from t in db.GetTable<Territory>()\r
523                              where t.TerritoryDescription.StartsWith("A")\r
524                              select t;\r
525             var toInclude2 = toInclude1.Concat(db.GetTable<Territory>().Where(terr => terr.TerritoryDescription.Contains("i")));\r
526 \r
527             var toTake = toInclude2.Distinct();\r
528 \r
529             int count = toTake.ToList().Count;\r
530 \r
531             Assert.AreEqual(27, count);\r
532         }\r
533 \r
534         [Test]\r
535         public void F26_DistinctUnion_Count()\r
536         {\r
537             var db = CreateDB();\r
538 \r
539             var toInclude1 = from t in db.GetTable<Territory>()\r
540                              where t.TerritoryDescription.StartsWith("A")\r
541                              select t;\r
542             var toInclude2 = toInclude1.Concat(db.GetTable<Territory>().Where(terr => terr.TerritoryDescription.Contains("i")));\r
543 \r
544             var toTake = toInclude2.Distinct();\r
545 \r
546             int count = toTake.Count();\r
547 \r
548             Assert.AreEqual(27, count);\r
549         }\r
550 \r
551 #if MSSQL || L2SQL\r
552 \r
553 #if L2SQL\r
554         [Explicit]\r
555 #endif\r
556         [Test]\r
557         public void F27_SelectEmployee_Identifier()\r
558         {\r
559             var db = CreateDB();\r
560             var q = from e in db.GetTable<EmployeeWithStringIdentifier>() where e.Identifier == "7" select e;\r
561             EmployeeWithStringIdentifier em = q.Single();\r
562 \r
563             Assert.AreEqual("King", em.LastName);\r
564         }\r
565 \r
566 #endif\r
567 \r
568         /// <summary>\r
569         /// the following three tests are from Jahmani's page\r
570         /// LinqToSQL: Comprehensive Support for SQLite, MS Access, SQServer2000/2005\r
571         /// http://www.codeproject.com/KB/linq/linqToSql_7.aspx?msg=2428251\r
572         /// </summary>\r
573         [Test(Description = "list of customers who have place orders that have all been shipped to the customers city.")]\r
574         public void O1_OperatorAll()\r
575         {\r
576             var q = from c in db.Customers\r
577                     where (from o in c.Orders\r
578                            select o).All(o => o.ShipCity == c.City)\r
579                     select new { c.CustomerID, c.ContactName };\r
580             var list = q.ToList();\r
581         }\r
582 \r
583         [Test(Description = "list of customers who have placed no orders")]\r
584         public void O2_OperatorAny()\r
585         {\r
586             //SELECT  t0.CustomerID, t0.ContactName\r
587             //FROM Customers AS t0\r
588             //WHERE  NOT  (\r
589             //(    SELECT  COUNT(*) \r
590             //    FROM Orders AS t1\r
591             //    WHERE (t1.CustomerID = t0.CustomerID)\r
592             //) > 0\r
593             //)\r
594             var q = from customer in db.Customers\r
595                     where !customer.Orders.Any()\r
596                     select new { customer.CustomerID, customer.ContactName };\r
597             //var q = from customer in db.Customers\r
598             //        where customer.Orders.Count() == 0\r
599             //        select new { customer.CustomerID, customer.ContactName };\r
600             var list = q.ToList();\r
601         }\r
602 \r
603         [Test(Description = "provide a list of customers and employees who live in London.")]\r
604         public void O3_OperatorUnion()\r
605         {\r
606             var q = (from c in db.Customers.Where(d => d.City == "London")\r
607                      select new { ContactName = c.ContactName })\r
608               .Union(from e in db.Employees.Where(f => f.City == "London")\r
609                      select new { ContactName = e.LastName });\r
610             var list = q.ToList();\r
611             Assert.IsTrue(list.Count > 0, "Expected some customers and employees from London");\r
612         }\r
613 \r
614         [Test]\r
615         public void O4_OperatorContains()\r
616         {\r
617             var ids = new Id[] { 1, 2, 3 };\r
618             Northwind db = CreateDB();\r
619 \r
620             //var q = from p in db.Products select p.ProductID;\r
621             //int productCount = q.Count();\r
622 \r
623             var products = from p in db.Products\r
624                            where ids.Contains((Id) p.ProductID)\r
625                            select p;\r
626 \r
627             Assert.AreEqual(3, products.Count());\r
628 \r
629         }\r
630 \r
631 \r
632     }\r
633 }\r