forked from nhibernate/nhibernate-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLinqQuerySamples.cs
executable file
·2103 lines (1822 loc) · 61.1 KB
/
LinqQuerySamples.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NHibernate.DomainModel.Northwind.Entities;
using NHibernate.Hql.Ast.ANTLR;
using NHibernate.Linq;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using NUnit.Framework;
namespace NHibernate.Test.Linq
{
[TestFixture]
public class LinqQuerySamples : LinqTestCase
{
class NotMappedEntity
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
[Test]
public void ShouldThrowForQueryOnNotMappedEntity()
{
var querySyntaxException = Assert.Throws<QuerySyntaxException>(() => session.Query<NotMappedEntity>().Select(x => x.Id).ToList());
Assert.That(querySyntaxException.Message, Does.Contain(nameof(NotMappedEntity)));
}
[Test]
public void ShouldThrowForQueryOnNotMappedEntityName()
{
var entityName = "SomeNamespace.NotMappedEntityName";
var querySyntaxException = Assert.Throws<QuerySyntaxException>(() => session.Query<NotMappedEntity>(entityName).ToList());
Assert.That(querySyntaxException.Message, Does.Contain(entityName));
}
[Test]
public void ShouldThrowForDmlQueryOnNotMappedEntity()
{
Assert.Multiple(
() =>
{
var querySyntaxException = Assert.Throws<QuerySyntaxException>(() => session.Query<NotMappedEntity>().Delete());
Assert.That(querySyntaxException.Message, Does.Contain(nameof(NotMappedEntity)));
var entityName = "SomeNamespace.NotMappedEntityName";
querySyntaxException = Assert.Throws<QuerySyntaxException>(() => session.Delete($"from {entityName}"));
Assert.That(querySyntaxException.Message, Does.Contain(entityName));
});
}
[Test]
public void GroupTwoQueriesAndSum()
{
//NH-3534
var queryWithAggregation = from o1 in db.Orders
from o2 in db.Orders
where o1.Customer.CustomerId == o2.Customer.CustomerId && o1.OrderDate == o2.OrderDate
group o1 by new { o1.Customer.CustomerId, o1.OrderDate } into g
select new { CustomerId = g.Key.CustomerId, LastOrderDate = g.Max(x => x.OrderDate) };
var result = queryWithAggregation.ToList();
Assert.IsNotNull(result);
Assert.IsNotEmpty(result);
}
[Category("WHERE")]
[Test(Description = "This sample uses WHERE to filter for Customers in London.")]
public void DLinq1()
{
IOrderedQueryable<Customer> q =
from c in db.Customers
where c.Address.City == "London"
orderby c.CustomerId
select c;
AssertByIds(q, new[]
{
"AROUT",
"BSBEV",
"CONSH",
"EASTC",
"NORTS",
"SEVES"
}, x => x.CustomerId);
}
[Category("WHERE")]
[Test(Description = "This sample uses WHERE to filter for Customers in London and then Madrid to ensure that the parameterization is working.")]
public void DLinq1b()
{
string city = "London";
IOrderedQueryable<Customer> q =
from c in db.Customers
where c.Address.City == city
orderby c.CustomerId
select c;
AssertByIds(q, new[]
{
"AROUT",
"BSBEV",
"CONSH",
"EASTC",
"NORTS",
"SEVES"
}, x => x.CustomerId);
city = "Madrid";
q = from c in db.Customers
where c.Address.City == city
orderby c.CustomerId
select c;
AssertByIds(q, new[]
{
"BOLID",
"FISSA",
"ROMEY"
}, x => x.CustomerId);
}
[Category("SELECT/DISTINCT")]
[Test(
Description =
"This sample uses SELECT and anonymous types to return a sequence of just the Customers' contact names and phone numbers."
)]
public void DLinq10()
{
var q =
from c in db.Customers
select new {c.ContactName, c.Address.PhoneNumber};
var items = q.ToList();
Assert.AreEqual(91, items.Count);
items.Each(x =>
{
Assert.IsNotNull(x.ContactName);
Assert.IsNotNull(x.PhoneNumber);
});
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses SELECT and anonymous types to return " +
"a sequence of just the Employees' names and phone numbers, " +
"with the FirstName and LastName fields combined into a single field, 'Name', " +
"and the HomePhone field renamed to Phone in the resulting sequence.")]
public void DLinq11()
{
var q =
from e in db.Employees
select new {Name = e.FirstName + " " + e.LastName, Phone = e.Address.PhoneNumber};
var items = q.ToList();
Assert.AreEqual(9, items.Count);
items.Each(x =>
{
Assert.IsNotNull(x.Name);
Assert.IsNotNull(x.Phone);
});
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses SELECT and anonymous types to return " +
"a sequence of all Products' IDs and a calculated value " +
"called HalfPrice which is set to the Product's UnitPrice " +
"divided by 2.")]
public void DLinq12()
{
var q =
from p in db.Products
select new {p.ProductId, p.UnitPrice, HalfPrice = p.UnitPrice/2};
foreach (var item in q)
{
Assert.AreEqual((item.UnitPrice/2), item.HalfPrice);
}
}
[Category("SELECT/DISTINCT")]
[Test]
public void DLinq12b()
{
var q =
from p in db.Products
select new {p.ProductId, p.UnitPrice, HalfPrice = p.UnitPrice*2};
foreach (var item in q)
{
Assert.IsTrue(item.UnitPrice*2 == item.HalfPrice);
}
}
[Category("SELECT/DISTINCT")]
[Test]
public void DLinq12c()
{
var q =
from p in db.Products
select new {p.ProductId, p.UnitPrice, HalfPrice = p.UnitPrice + 2};
foreach (var item in q)
{
Assert.IsTrue(item.UnitPrice + 2 == item.HalfPrice);
}
}
[Category("SELECT/DISTINCT")]
[Test]
public void DLinq12d()
{
var q =
from p in db.Products
select new {p.ProductId, p.UnitPrice, HalfPrice = p.UnitPrice - 2};
foreach (var item in q)
{
Assert.IsTrue(item.UnitPrice - 2 == item.HalfPrice);
}
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses SELECT and a conditional statment to return a sequence of product " +
" name and product availability.")]
public void DLinq13()
{
var q =
from p in db.Products
select new {p.Name, Availability = p.UnitsInStock - p.UnitsOnOrder < 0 ? "Out Of Stock" : "In Stock"};
ObjectDumper.Write(q, 1);
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses SELECT and a known type to return a sequence of employees' names.")]
public void DLinq14()
{
IQueryable<Name> q =
from e in db.Employees
select new Name {FirstName = e.FirstName, LastName = e.LastName};
ObjectDumper.Write(q, 1);
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses SELECT and WHERE to return a sequence of " +
"just the London Customers' contact names.")]
public void DLinq15()
{
IQueryable<string> q =
from c in db.Customers
where c.Address.City == "London"
select c.ContactName;
ObjectDumper.Write(q);
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses SELECT and anonymous types to return " +
"a shaped subset of the data about Customers.")]
public void DLinq16()
{
if (!Dialect.SupportsScalarSubSelects)
Assert.Ignore(Dialect.GetType().Name + " does not support scalar sub-queries");
var q =
from c in db.Customers
select new
{
c.CustomerId,
CompanyInfo = new {c.CompanyName, c.Address.City, c.Address.Country},
ContactInfo = new {c.ContactName, c.ContactTitle},
Count = c.Orders.Count()
};
ObjectDumper.Write(q, 1);
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses nested queries to return a sequence of " +
"all orders containing their OrderId, a subsequence of the " +
"items in the order where there is a discount, and the money " +
"saved if shipping is not included.")]
[Ignore("TODO - nested select")]
public void DLinq17()
{
using (ISession s = OpenSession())
{
/////////////
///// Flattened Select
/////////////
//// In HQL select, get all the data that's needed
//var dbOrders =
// s.CreateQuery("select o.OrderId, od, o.Freight from Order o join o.OrderLines od").List<object[]>();
//// Now group by the items in the parent select, grouping the items in the child select (note lookups on object[], ala SelectClauseVisitor)
//// Note the casts to get the types correct. Need to check if SelectClauseVisitor handles that, but think it does
//var a = from o in dbOrders
// group new { OrderLine = (OrderLine)o[1], Freight = (Decimal?)o[2] } by new { OrderId = (int) o[0] }
// into g
// select
// // Select the parent items, and the child items in a nested select
// new { g.Key.OrderId, DiscountedProducts = from e in g select new { e.OrderLine, FreeShippingDiscount = e.Freight } };
//a.ToList();
/////////////
///// Nested Select
/////////////
//var dbOrders2 = s.CreateQuery("select o.OrderId from Order o").List<int>();
//var q2 = from o in dbOrders2
// select new
// {
// OrderId = o,
// DiscountedProducts =
// from subO in db.Orders
// where subO.OrderId == o
// from orderLine in subO.OrderLines
// select new { orderLine, FreeShippingDiscount = subO.Freight }
// };
//q2.ToList();
///////////
///// Batching Select
///////////
var dbOrders3 = s.CreateQuery("select o.OrderId from Order o").List<int>();
//var q3 = dbOrders3.SubQueryBatcher(orderId => orderId,
// ids => from subO in db.Orders.ToList() // Note that ToList is just because current group by code is incorrent in our linq provider
// where ids.Contains(subO.OrderId)
// from orderLine in subO.OrderLines
// group new {orderLine, FreeShippingDiscount = subO.Freight}
// by subO.OrderId
// into g
// select g
// )
// .Select((input, index) => new
// {
// OrderId = input.Item,
// DiscountedProducts = input.Batcher.GetData(index)
// });
// This is what we want:
//var q3 = dbOrders3.SubQueryBatcher(orderId => orderId,
// ids => db.Orders
// .Where(o => ids.Contains(o.OrderId))
// .Select(o => new {o.OrderId, o.OrderLines, o.Freight}).ToList()
// .GroupBy(k => k.OrderId, e => new { e.OrderLines, FreeShippingDiscount = e.Freight})
// )
// .Select((input, index) => new
// {
// OrderId = input.Item,
// DiscountedProducts = input.Batcher.GetData(index)
// });
// This is what we're using since our provider can't yet handle the in or the group by clauses correctly (note the ToList and the Where clause moving to get us into Linq to Objects world)
var q3 = dbOrders3.SubQueryBatcher(orderId => orderId,
ids =>
(from o in db.Orders
from ol in o.OrderLines
select new { OrderLines = ol, FreeShippingDiscount = o.Freight, o.OrderId })
.ToList()
.Where(o => ids.Contains(o.OrderId))
.GroupBy(k => k.OrderId, e => new { e.OrderLines, e.FreeShippingDiscount })
)
.Select((input, index) => new
{
OrderId = input.Item,
DiscountedProducts = input.Batcher.GetData(index)
});
foreach (var x in q3)
{
Console.WriteLine(x.OrderId);
foreach (var y in x.DiscountedProducts)
{
Console.WriteLine(y.FreeShippingDiscount);
}
}
q3.ToList();
}
var q =
from o in db.Orders
select new
{
o.OrderId,
DiscountedProducts =
from od in o.OrderLines
// from od in o.OrderLines.Cast<OrderLine>()
where od.Discount > 0.0m
select od, FreeShippingDiscount = o.Freight
};
ObjectDumper.Write(q, 1);
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses nested queries to return a sequence of " +
"all orders containing their OrderId, a subsequence of the " +
"items in the order where there is a discount, and the money " +
"saved if shipping is not included.")]
public void DLinq17b()
{
var q =
from o in db.Orders
select new
{
o.OrderId,
DiscountedProducts =
from od in o.OrderLines
where od.Discount > 0.0m
select new {od.Quantity, od.UnitPrice},
FreeShippingDiscount = o.Freight
};
ObjectDumper.Write(q, 1);
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses nested queries to return a sequence of " +
"all orders containing their OrderId, a subsequence of the " +
"items in the order where there is a discount, and the money " +
"saved if shipping is not included.")]
[Ignore("TODO - nested select")]
public void DLinq17c()
{
var q =
from o in db.Orders
select new
{
o.OrderId,
DiscountedProducts =
from od in o.OrderLines
// from od in o.OrderLines.Cast<OrderLine>()
where od.Discount > 0.0m
orderby od.Discount descending
select od,
FreeShippingDiscount = o.Freight
};
ObjectDumper.Write(q, 1);
}
[Category("SELECT/DISTINCT")]
[Test(Description = "This sample uses Distinct to select a sequence of the unique cities " +
"that have Customers.")]
public void DLinq18()
{
IQueryable<string> q = (
from c in db.Customers
select c.Address.City)
.Distinct();
ObjectDumper.Write(q);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Count to find the number of Customers in the database.")]
public void DLinq19()
{
int q = db.Customers.Count();
Console.WriteLine(q);
}
[Category("WHERE")]
[Test(Description = "This sample uses WHERE to filter for Employees hired during or after 1994.")]
public void DLinq2()
{
IQueryable<Employee> q =
from e in db.Employees
where e.HireDate >= new DateTime(1994, 1, 1)
select e;
AssertByIds(q, new[] {7, 8, 9}, x => x.EmployeeId);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Count to find the number of Products in the database " +
"that are not discontinued.")]
public void DLinq20()
{
int q = db.Products.Count(p => !p.Discontinued);
Console.WriteLine(q);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Sum to find the total freight over all Orders.")]
public void DLinq21()
{
decimal? q = db.Orders.Select(o => o.Freight).Sum();
Console.WriteLine(q);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Sum to find the total number of units on order over all Products.")]
public void DLinq22()
{
int? q = db.Products.Sum(p => p.UnitsOnOrder);
Console.WriteLine(q);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Min to find the lowest unit price of any Product.")]
public void DLinq23()
{
decimal? q = db.Products.Select(p => p.UnitPrice).Min();
Console.WriteLine(q);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Min to find the lowest freight of any Order.")]
public void DLinq24()
{
decimal? q = db.Orders.Min(o => o.Freight);
Console.WriteLine(q);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Min to find the Products that have the lowest unit price " +
"in each category.")]
[Ignore("TODO nested aggregating group by")]
public void DLinq25()
{
using (var session = OpenSession())
{
var output = session
.CreateQuery(
"select p.Category.CategoryId, p from Product p where p.UnitPrice = (select min(p2.UnitPrice) from Product p2 where p.Category.CategoryId = p2.Category.CategoryId)"
)
.List<object[]>()
.GroupBy(input => input[0])
.Select(input => new {CategoryId = (int) input.Key, CheapestProducts = from g in input select (Product) g[1]});
}
/*
* From g, only using g.Key, min(UnitPrice), g
* - g.Key is fine
* - min(UnitPrice) is fine
* - g is the problem. Can't just issue a single select since it's non-aggregating
* However, don't want to loose the aggregate; need that processed in the DB
*
* To get additional information over and above g.Key and any aggregates, need a where clause against the aggregate:
*
* select xxx, yyy, zzz from Product p where p.UnitPrice = (select min(p2.UnitPrice) from Product p2)
*
* the outer where comes from the inner where in the queryModel:
*
* where p2.UnitPrice == g.Min(p3 => p3.UnitPrice)
*
* also need additional constraints on the aggregate to fulfil the groupby requirements:
*
* where p.Category.CategoryId = p2.Category.CategoryId
*
* so join the inner select to the outer select using the group by criteria
*
* finally, need to do some client-side processing to get the "shape" correct
*
*/
var categories =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
CategoryId = g.Key,
CheapestProducts =
(IEnumerable<Product>) (from p2 in g
where p2.UnitPrice == g.Min(p3 => p3.UnitPrice)
select p2)
};
Console.WriteLine(ObjectDumper.Write(categories, 1));
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Max to find the latest hire date of any Employee.")]
public void DLinq26()
{
DateTime? q = db.Employees.Select(e => e.HireDate).Max();
Console.WriteLine(q);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Max to find the most units in stock of any Product.")]
public void DLinq27()
{
int? q = db.Products.Max(p => p.UnitsInStock);
Console.WriteLine(q);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Max to find the Products that have the highest unit price " +
"in each category.")]
[Ignore("TODO nested aggregating group by")]
public void DLinq28()
{
var categories =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
g.Key,
MostExpensiveProducts =
from p2 in g
where p2.UnitPrice == g.Max(p3 => p3.UnitPrice)
select p2
};
ObjectDumper.Write(categories, 1);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Average to find the average freight of all Orders.")]
public void DLinq29()
{
decimal? q = db.Orders.Select(o => o.Freight).Average();
Console.WriteLine(q);
}
[Category("WHERE")]
[Test(
Description =
"This sample uses WHERE to filter for Products that have stock below their reorder level and are not discontinued."
)]
public void DLinq3()
{
IQueryable<Product> q =
from p in db.Products
where p.UnitsInStock <= p.ReorderLevel && !p.Discontinued
select p;
AssertByIds(q, new[] {2, 3, 11, 21, 30, 31, 32, 37, 43, 45, 48, 49, 56, 64, 66, 68, 70, 74,},
x => x.ProductId);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Average to find the average unit price of all Products.")]
public void DLinq30()
{
decimal? q = db.Products.Average(p => p.UnitPrice);
Console.WriteLine(q);
}
[Category("COUNT/SUM/MIN/MAX/AVG")]
[Test(Description = "This sample uses Average to find the Products that have unit price higher than " +
"the average unit price of the category for each category.")]
[Ignore("TODO nested aggregating group by")]
public void DLinq31()
{
var categories =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
g.Key,
ExpensiveProducts =
from p2 in g
where p2.UnitPrice > g.Average(p3 => p3.UnitPrice)
select p2
};
ObjectDumper.Write(categories, 1);
}
[Category("ORDER BY")]
[Test(Description = "This sample uses orderby to sort Employees by hire date.")]
public void DLinq36()
{
IOrderedQueryable<Employee> q =
from e in db.Employees
orderby e.HireDate
select e;
ObjectDumper.Write(q);
}
[Category("ORDER BY")]
[Test(Description = "This sample uses where and orderby to sort Orders " +
"shipped to London by freight.")]
public void DLinq37()
{
IOrderedQueryable<Order> q =
from o in db.Orders
where o.ShippingAddress.City == "London"
orderby o.Freight
select o;
ObjectDumper.Write(q);
}
[Category("ORDER BY")]
[Test(Description = "This sample uses orderby to sort Products " +
"by unit price from highest to lowest.")]
public void DLinq38()
{
IOrderedQueryable<Product> q =
from p in db.Products
orderby p.UnitPrice descending
select p;
ObjectDumper.Write(q);
}
[Category("ORDER BY")]
[Test(Description = "This sample uses a compound orderby to sort Customers " +
"by city and then contact name.")]
public void DLinq39()
{
IOrderedQueryable<Customer> q =
from c in db.Customers
orderby c.Address.City , c.ContactName
select c;
ObjectDumper.Write(q);
}
[Category("WHERE")]
[Test(
Description =
"This sample uses WHERE to filter for Products that have stock below their reorder level and are not discontinued."
)]
public void DLinq3b()
{
IQueryable<Product> q =
from p in db.Products
where p.UnitsInStock <= p.ReorderLevel && p.Discontinued == false
select p;
AssertByIds(q, new[] {2, 3, 11, 21, 30, 31, 32, 37, 43, 45, 48, 49, 56, 64, 66, 68, 70, 74,},
x => x.ProductId);
}
[Category("WHERE")]
[Test(
Description =
"This sample uses WHERE to filter out Products that are either UnitPrice is greater than 10 or is discontinued."
)]
public void DLinq4()
{
IQueryable<Product> q =
from p in db.Products
where p.UnitPrice > 10m || p.Discontinued
select p;
AssertByIds(q,
new[]
{
1, 2, 4, 5, 6, 7, 8, 9, 10,
11, 12, 14, 15, 16, 17, 18, 20, 22,
24, 25, 26, 27, 28, 29, 30, 31, 32,
34, 35, 36, 37, 38, 39, 40, 42, 43,
44, 46, 48, 49, 50, 51, 53, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73, 76,
77,
}, x => x.ProductId);
}
[Category("ORDER BY")]
[Test(Description = "This sample uses orderby to sort Orders from EmployeeId 1 " +
"by ship-to country, and then by freight from highest to lowest.")]
public void DLinq40()
{
IOrderedQueryable<Order> q =
from o in db.Orders
where o.Employee.EmployeeId == 1
orderby o.ShippingAddress.Country , o.Freight descending
select o;
ObjectDumper.Write(q);
}
[Category("ORDER BY")]
[Test(Description = "This sample uses Orderby, Max and Group By to find the Products that have " +
"the highest unit price in each category, and sorts the group by category id.")]
[Ignore("TODO nested aggregating group by")]
public void DLinq41()
{
var categories =
from p in db.Products
group p by p.Category.CategoryId
into g
orderby g.Key
select new
{
g.Key,
MostExpensiveProducts =
from p2 in g
where p2.UnitPrice == g.Max(p3 => p3.UnitPrice)
select p2
};
ObjectDumper.Write(categories, 1);
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses group by to partition Products by " +
"CategoryId.")]
public void DLinq42()
{
IQueryable<IGrouping<int, Product>> q =
from p in db.Products
group p by p.Category.CategoryId
into g
select g;
ObjectDumper.Write(q, 1);
foreach (var o in q)
{
Console.WriteLine("\n{0}\n", o);
foreach (Product p in o)
{
ObjectDumper.Write(p);
}
}
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses group by and Max " +
"to find the maximum unit price for each CategoryId.")]
public void DLinq43()
{
var q =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
g.Key,
MaxPrice = g.Max(p => p.UnitPrice)
};
ObjectDumper.Write(q, 1);
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses group by and Min " +
"to find the minimum unit price for each CategoryId.")]
public void DLinq44()
{
var q =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
g.Key,
MinPrice = g.Min(p => p.UnitPrice)
};
ObjectDumper.Write(q, 1);
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses group by and Average " +
"to find the average UnitPrice for each CategoryId.")]
public void DLinq45()
{
var q =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
g.Key,
AveragePrice = g.Average(p2 => p2.UnitPrice)
};
ObjectDumper.Write(q, 1);
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses group by and Sum " +
"to find the total UnitPrice for each CategoryId.")]
public void DLinq46()
{
var q =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
g.Key,
TotalPrice = g.Sum(p => p.UnitPrice)
};
ObjectDumper.Write(q, 1);
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses group by and Count " +
"to find the number of Products in each CategoryId.")]
public void DLinq47()
{
var q =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
g.Key,
NumProducts = g.Count()
};
ObjectDumper.Write(q, 1);
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses group by and Count " +
"to find the number of Products in each CategoryId " +
"that are discontinued.")]
public void DLinq48()
{
var q =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
g.Key,
NumProducts = g.Count(p => p.Discontinued)
};
ObjectDumper.Write(q, 1);
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses group by and Count " +
"to find the number of Products in each CategoryId " +
"that are not discontinued.")]
public void DLinq48b()
{
var q =
from p in db.Products
group p by p.Category.CategoryId
into g
select new
{
g.Key,
NumProducts = g.Count(p => !p.Discontinued)
};
ObjectDumper.Write(q, 1);
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses a where clause after a group by clause " +
"to find all categories that have at least 10 products.")]
public void DLinq49()
{
var q =
from p in db.Products
group p by p.Category.CategoryId
into g
where g.Count() >= 10
select new
{
g.Key,
ProductCount = g.Count()
};
ObjectDumper.Write(q, 1);
}
[Category("WHERE")]
[Test(Description = "This sample calls WHERE twice to filter out Products that UnitPrice is greater than 10" +
" and is discontinued.")]
public void DLinq5()
{
IEnumerable<Product> q =
db.Products.Where(p => p.UnitPrice > 10m).Where(p => p.Discontinued);
AssertByIds(q, new[] {5, 9, 17, 28, 29, 42, 53,}, x => x.ProductId);
}
[Category("GROUP BY/HAVING")]
[Test(Description = "This sample uses Group By to group products by CategoryId and SupplierId.")]
public void DLinq50()
{
//var prods = db.Products.ToList();
var categories =
from p in db.Products
group p by new {p.Category.CategoryId, p.Supplier.SupplierId}
into g
select new {g.Key, g};
var nhOutput = ObjectDumper.Write(categories, 1);