@@ -768,6 +768,26 @@ from o in c.Orders
768
768
}
769
769
}
770
770
771
+ [ Category ( "JOIN" ) ]
772
+ [ Test ( Description = "This sample uses foreign key navigation in the " +
773
+ "from clause to select all orders for customers in London." ) ]
774
+ public async Task DLinqJoin1LeftJoinAsync ( )
775
+ {
776
+ IQueryable < Order > q =
777
+ from c in db . Customers
778
+ from o in c . Orders . DefaultIfEmpty ( )
779
+ where c . Address . City == "London"
780
+ select o ;
781
+
782
+ using ( var sqlSpy = new SqlLogSpy ( ) )
783
+ {
784
+ await ( ObjectDumper . WriteAsync ( q ) ) ;
785
+
786
+ var sql = sqlSpy . GetWholeLog ( ) ;
787
+ Assert . That ( GetTotalOccurrences ( sql , "left outer join" ) , Is . EqualTo ( 1 ) ) ;
788
+ }
789
+ }
790
+
771
791
[ Category ( "JOIN" ) ]
772
792
[ Test ( Description = "This sample shows how to construct a join where one side is nullable and the other isn't." ) ]
773
793
public async Task DLinqJoin10Async ( )
@@ -974,6 +994,26 @@ join o in db.Orders on c.CustomerId equals o.Customer.CustomerId
974
994
}
975
995
}
976
996
997
+ [ Category ( "JOIN" ) ]
998
+ [ Test ( Description = "This sample explictly joins two tables and projects results from both tables." ) ]
999
+ public async Task DLinqJoin5aLeftJoinAsync ( )
1000
+ {
1001
+ var q =
1002
+ from c in db . Customers
1003
+ join o in db . Orders on c . CustomerId equals o . Customer . CustomerId into orders
1004
+ from o in orders . DefaultIfEmpty ( )
1005
+ where o != null
1006
+ select new { c . ContactName , o . OrderId } ;
1007
+
1008
+ using ( var sqlSpy = new SqlLogSpy ( ) )
1009
+ {
1010
+ await ( ObjectDumper . WriteAsync ( q ) ) ;
1011
+
1012
+ var sql = sqlSpy . GetWholeLog ( ) ;
1013
+ Assert . That ( GetTotalOccurrences ( sql , "left outer join" ) , Is . EqualTo ( 1 ) ) ;
1014
+ }
1015
+ }
1016
+
977
1017
[ Category ( "JOIN" ) ]
978
1018
[ Test ( Description = "This sample explictly joins two tables and projects results from both tables using a group join." ) ]
979
1019
public async Task DLinqJoin5bAsync ( )
@@ -1030,6 +1070,21 @@ join o in db.Orders on
1030
1070
}
1031
1071
}
1032
1072
1073
+ [ Category ( "JOIN" ) ]
1074
+ [ Test ( Description = "This sample explictly joins two tables with a composite key and projects results from both tables." ) ]
1075
+ public void DLinqJoin5dLeftJoinAsync ( )
1076
+ {
1077
+ var q =
1078
+ from c in db . Customers
1079
+ join o in db . Orders on
1080
+ new { c . CustomerId , HasContractTitle = c . ContactTitle != null } equals
1081
+ new { o . Customer . CustomerId , HasContractTitle = o . Customer . ContactTitle != null } into orders
1082
+ from o in orders . DefaultIfEmpty ( )
1083
+ select new { c . ContactName , o . OrderId } ;
1084
+
1085
+ Assert . ThrowsAsync < NotSupportedException > ( ( ) => ObjectDumper . WriteAsync ( q ) ) ;
1086
+ }
1087
+
1033
1088
[ Category ( "JOIN" ) ]
1034
1089
[ Test ( Description = "This sample joins two tables and projects results from the first table." ) ]
1035
1090
public async Task DLinqJoin5eAsync ( )
@@ -1049,6 +1104,26 @@ join o in db.Orders on c.CustomerId equals o.Customer.CustomerId
1049
1104
}
1050
1105
}
1051
1106
1107
+ [ Category ( "JOIN" ) ]
1108
+ [ Test ( Description = "This sample joins two tables and projects results from the first table." ) ]
1109
+ public async Task DLinqJoin5eLeftJoinAsync ( )
1110
+ {
1111
+ var q =
1112
+ from c in db . Customers
1113
+ join o in db . Orders on c . CustomerId equals o . Customer . CustomerId into orders
1114
+ from o in orders . DefaultIfEmpty ( )
1115
+ where c . ContactName != null
1116
+ select o ;
1117
+
1118
+ using ( var sqlSpy = new SqlLogSpy ( ) )
1119
+ {
1120
+ await ( ObjectDumper . WriteAsync ( q ) ) ;
1121
+
1122
+ var sql = sqlSpy . GetWholeLog ( ) ;
1123
+ Assert . That ( GetTotalOccurrences ( sql , "left outer join" ) , Is . EqualTo ( 1 ) ) ;
1124
+ }
1125
+ }
1126
+
1052
1127
[ Category ( "JOIN" ) ]
1053
1128
[ TestCase ( Description = "This sample explictly joins two tables with a composite key and projects results from both tables." ) ]
1054
1129
public async Task DLinqJoin5fAsync ( )
@@ -1070,6 +1145,28 @@ join c in db.Customers on
1070
1145
}
1071
1146
}
1072
1147
1148
+ [ Category ( "JOIN" ) ]
1149
+ [ TestCase ( Description = "This sample explictly joins two tables with a composite key and projects results from both tables." ) ]
1150
+ public async Task DLinqJoin5fLeftJoinAsync ( )
1151
+ {
1152
+ var q =
1153
+ from o in db . Orders
1154
+ join c in db . Customers on
1155
+ new { o . Customer . CustomerId , HasContractTitle = o . Customer . ContactTitle != null } equals
1156
+ new { c . CustomerId , HasContractTitle = c . ContactTitle != null } into customers
1157
+ from c in customers . DefaultIfEmpty ( )
1158
+ select new { c . ContactName , o . OrderId } ;
1159
+
1160
+ using ( var sqlSpy = new SqlLogSpy ( ) )
1161
+ {
1162
+ await ( ObjectDumper . WriteAsync ( q ) ) ;
1163
+
1164
+ var sql = sqlSpy . GetWholeLog ( ) ;
1165
+ Assert . That ( GetTotalOccurrences ( sql , "left outer join" ) , Is . EqualTo ( 2 ) ) ;
1166
+ Assert . That ( GetTotalOccurrences ( sql , "inner join" ) , Is . EqualTo ( 0 ) ) ;
1167
+ }
1168
+ }
1169
+
1073
1170
[ Category ( "JOIN" ) ]
1074
1171
[ Test ( Description = "This sample explictly joins three tables and projects results from each of them." ) ]
1075
1172
public async Task DLinqJoin6Async ( )
@@ -1092,6 +1189,28 @@ join e in db.Employees on c.Address.City equals e.Address.City into emps
1092
1189
}
1093
1190
}
1094
1191
1192
+ [ Category ( "JOIN" ) ]
1193
+ [ Test (
1194
+ Description =
1195
+ "This sample shows how to get LEFT OUTER JOIN by using DefaultIfEmpty(). The DefaultIfEmpty() method returns null when there is no Order for the Employee."
1196
+ ) ]
1197
+ public async Task DLinqJoin7Async ( )
1198
+ {
1199
+ var q =
1200
+ from e in db . Employees
1201
+ join o in db . Orders on e equals o . Employee into ords
1202
+ from o in ords . DefaultIfEmpty ( )
1203
+ select new { e . FirstName , e . LastName , Order = o } ;
1204
+
1205
+ using ( var sqlSpy = new SqlLogSpy ( ) )
1206
+ {
1207
+ await ( ObjectDumper . WriteAsync ( q ) ) ;
1208
+
1209
+ var sql = sqlSpy . GetWholeLog ( ) ;
1210
+ Assert . That ( GetTotalOccurrences ( sql , "left outer join" ) , Is . EqualTo ( 1 ) ) ;
1211
+ }
1212
+ }
1213
+
1095
1214
[ Category ( "JOIN" ) ]
1096
1215
[ Test ( Description = "This sample projects a 'let' expression resulting from a join." ) ]
1097
1216
public async Task DLinqJoin8Async ( )
@@ -1156,6 +1275,51 @@ from d in details
1156
1275
Assert . AreEqual ( expected . Count , actual . Count ) ;
1157
1276
}
1158
1277
1278
+ [ Category ( "JOIN" ) ]
1279
+ [ TestCase ( true , Description = "This sample shows a group left join with a composite key." ) ]
1280
+ [ TestCase ( false , Description = "This sample shows a group left join with a composite key." ) ]
1281
+ public async Task DLinqJoin9LeftJoinAsync ( bool useCrossJoin )
1282
+ {
1283
+ if ( useCrossJoin && ! Dialect . SupportsCrossJoin )
1284
+ {
1285
+ Assert . Ignore ( "Dialect does not support cross join." ) ;
1286
+ }
1287
+
1288
+ ICollection expected , actual ;
1289
+ expected =
1290
+ ( from o in db . Orders . ToList ( )
1291
+ from p in db . Products . ToList ( )
1292
+ join d in db . OrderLines . ToList ( )
1293
+ on new { o . OrderId , p . ProductId } equals new { d . Order . OrderId , d . Product . ProductId }
1294
+ into details
1295
+ from d in details . DefaultIfEmpty ( )
1296
+ where d != null && d . UnitPrice > 50
1297
+ select new { o . OrderId , p . ProductId , d . UnitPrice } ) . ToList ( ) ;
1298
+
1299
+ using ( var substitute = SubstituteDialect ( ) )
1300
+ using ( var sqlSpy = new SqlLogSpy ( ) )
1301
+ {
1302
+ ClearQueryPlanCache ( ) ;
1303
+ substitute . Value . SupportsCrossJoin . Returns ( useCrossJoin ) ;
1304
+
1305
+ actual =
1306
+ await ( ( from o in db . Orders
1307
+ from p in db . Products
1308
+ join d in db . OrderLines
1309
+ on new { o . OrderId , p . ProductId } equals new { d . Order . OrderId , d . Product . ProductId }
1310
+ into details
1311
+ from d in details . DefaultIfEmpty ( )
1312
+ where d != null && d . UnitPrice > 50
1313
+ select new { o . OrderId , p . ProductId , d . UnitPrice } ) . ToListAsync ( ) ) ;
1314
+
1315
+ var sql = sqlSpy . GetWholeLog ( ) ;
1316
+ Assert . That ( sql , Does . Contain ( useCrossJoin ? "cross join" : "inner join" ) ) ;
1317
+ Assert . That ( GetTotalOccurrences ( sql , "left outer join" ) , Is . EqualTo ( 1 ) ) ;
1318
+ }
1319
+
1320
+ Assert . AreEqual ( expected . Count , actual . Count ) ;
1321
+ }
1322
+
1159
1323
[ Category ( "JOIN" ) ]
1160
1324
[ Test ( Description = "This sample shows a join which is then grouped" ) ]
1161
1325
public async Task DLinqJoin9bAsync ( )
@@ -1186,5 +1350,26 @@ join s2 in db.Employees on s.Superior.EmployeeId equals s2.EmployeeId
1186
1350
Assert . That ( GetTotalOccurrences ( sql , "inner join" ) , Is . EqualTo ( 2 ) ) ;
1187
1351
}
1188
1352
}
1353
+
1354
+ [ Category ( "JOIN" ) ]
1355
+ [ Test ( Description = "This sample shows how to join multiple tables using a left join." ) ]
1356
+ public async Task DLinqJoin10aLeftJoinAsync ( )
1357
+ {
1358
+ var q =
1359
+ from e in db . Employees
1360
+ join s in db . Employees on e . Superior . EmployeeId equals s . EmployeeId into sup
1361
+ from s in sup . DefaultIfEmpty ( )
1362
+ join s2 in db . Employees on s . Superior . EmployeeId equals s2 . EmployeeId into sup2
1363
+ from s2 in sup2 . DefaultIfEmpty ( )
1364
+ select new { e . FirstName , SuperiorName = s . FirstName , Superior2Name = s2 . FirstName } ;
1365
+
1366
+ using ( var sqlSpy = new SqlLogSpy ( ) )
1367
+ {
1368
+ await ( ObjectDumper . WriteAsync ( q ) ) ;
1369
+
1370
+ var sql = sqlSpy . GetWholeLog ( ) ;
1371
+ Assert . That ( GetTotalOccurrences ( sql , "left outer join" ) , Is . EqualTo ( 2 ) ) ;
1372
+ }
1373
+ }
1189
1374
}
1190
1375
}
0 commit comments