14
14
using System . Linq . Expressions ;
15
15
using System . Text . RegularExpressions ;
16
16
using NHibernate . DomainModel . Northwind . Entities ;
17
- using NUnit . Framework ;
18
17
using NHibernate . Linq ;
18
+ using NUnit . Framework ;
19
19
20
20
namespace NHibernate . Test . Linq
21
21
{
@@ -30,7 +30,8 @@ public async Task UsingArrayParameterTwiceAsync()
30
30
var ids = new [ ] { 11008 , 11019 , 11039 } ;
31
31
await ( AssertTotalParametersAsync (
32
32
db . Orders . Where ( o => ids . Contains ( o . OrderId ) && ids . Contains ( o . OrderId ) ) ,
33
- ids . Length ) ) ;
33
+ ids . Length ,
34
+ 1 ) ) ;
34
35
}
35
36
36
37
[ Test ]
@@ -40,7 +41,8 @@ public async Task UsingTwoArrayParametersAsync()
40
41
var ids2 = new [ ] { 11008 , 11019 , 11039 } ;
41
42
await ( AssertTotalParametersAsync (
42
43
db . Orders . Where ( o => ids . Contains ( o . OrderId ) && ids2 . Contains ( o . OrderId ) ) ,
43
- ids . Length + ids2 . Length ) ) ;
44
+ ids . Length + ids2 . Length ,
45
+ 2 ) ) ;
44
46
}
45
47
46
48
[ Test ]
@@ -49,7 +51,8 @@ public async Task UsingListParameterTwiceAsync()
49
51
var ids = new List < int > { 11008 , 11019 , 11039 } ;
50
52
await ( AssertTotalParametersAsync (
51
53
db . Orders . Where ( o => ids . Contains ( o . OrderId ) && ids . Contains ( o . OrderId ) ) ,
52
- ids . Count ) ) ;
54
+ ids . Count ,
55
+ 1 ) ) ;
53
56
}
54
57
55
58
[ Test ]
@@ -59,7 +62,8 @@ public async Task UsingTwoListParametersAsync()
59
62
var ids2 = new List < int > { 11008 , 11019 , 11039 } ;
60
63
await ( AssertTotalParametersAsync (
61
64
db . Orders . Where ( o => ids . Contains ( o . OrderId ) && ids2 . Contains ( o . OrderId ) ) ,
62
- ids . Count + ids2 . Count ) ) ;
65
+ ids . Count + ids2 . Count ,
66
+ 2 ) ) ;
63
67
}
64
68
65
69
[ Test ]
@@ -108,6 +112,16 @@ public async Task UsingNegateValueTypeParameterAsync()
108
112
2 ) ) ;
109
113
}
110
114
115
+ [ Test ]
116
+ public async Task UsingValueTypeParameterInArrayAsync ( )
117
+ {
118
+ var id = 11008 ;
119
+ await ( AssertTotalParametersAsync (
120
+ db . Orders . Where ( o => new [ ] { id , 11019 } . Contains ( o . OrderId ) && new [ ] { id , 11019 } . Contains ( o . OrderId ) ) ,
121
+ 4 ,
122
+ 2 ) ) ;
123
+ }
124
+
111
125
[ Test ]
112
126
public async Task UsingTwoValueTypeParametersAsync ( )
113
127
{
@@ -156,6 +170,22 @@ public async Task UsingTwoObjectPropertyParametersAsync()
156
170
2 ) ) ;
157
171
}
158
172
173
+ [ Test ]
174
+ public async Task UsingParameterInWhereSkipTakeAsync ( )
175
+ {
176
+ var value3 = 1 ;
177
+ var q1 = db . Products . Where ( o => o . ProductId < value3 ) . Take ( value3 ) . Skip ( value3 ) ;
178
+ await ( AssertTotalParametersAsync ( q1 , 3 ) ) ;
179
+ }
180
+
181
+ [ Test ]
182
+ public async Task UsingParameterInTwoWhereAsync ( )
183
+ {
184
+ var value3 = 1 ;
185
+ var q1 = db . Products . Where ( o => o . ProductId < value3 ) . Where ( o => o . ProductId < value3 ) ;
186
+ await ( AssertTotalParametersAsync ( q1 , 1 ) ) ;
187
+ }
188
+
159
189
[ Test ]
160
190
public async Task UsingObjectNestedPropertyParameterTwiceAsync ( )
161
191
{
@@ -213,18 +243,142 @@ public async Task UsingObjectPropertyParameterWithThirdLevelClosureAsync()
213
243
1 ) ) ;
214
244
}
215
245
216
- private static async Task AssertTotalParametersAsync < T > ( IQueryable < T > query , int parameterNumber , CancellationToken cancellationToken = default ( CancellationToken ) )
246
+ [ Test ]
247
+ public async Task UsingParameterInDMLInsertIntoFourTimesAsync ( )
248
+ {
249
+ var value = "test" ;
250
+ await ( AssertTotalParametersAsync (
251
+ QueryMode . Insert ,
252
+ db . Customers . Where ( c => c . CustomerId == value ) ,
253
+ x => new Customer { CustomerId = value , ContactName = value , CompanyName = value } ,
254
+ 4 ) ) ;
255
+ }
256
+
257
+ [ Test ]
258
+ public async Task UsingFourParametersInDMLInsertIntoAsync ( )
259
+ {
260
+ var value = "test" ;
261
+ var value2 = "test" ;
262
+ var value3 = "test" ;
263
+ var value4 = "test" ;
264
+ await ( AssertTotalParametersAsync (
265
+ QueryMode . Insert ,
266
+ db . Customers . Where ( c => c . CustomerId == value3 ) ,
267
+ x => new Customer { CustomerId = value4 , ContactName = value2 , CompanyName = value } ,
268
+ 4 ) ) ;
269
+ }
270
+
271
+ [ Test ]
272
+ public async Task UsingParameterInDMLUpdateThreeTimesAsync ( )
273
+ {
274
+ var value = "test" ;
275
+ await ( AssertTotalParametersAsync (
276
+ QueryMode . Update ,
277
+ db . Customers . Where ( c => c . CustomerId == value ) ,
278
+ x => new Customer { ContactName = value , CompanyName = value } ,
279
+ 3 ) ) ;
280
+ }
281
+
282
+ [ Test ]
283
+ public async Task UsingThreeParametersInDMLUpdateAsync ( )
284
+ {
285
+ var value = "test" ;
286
+ var value2 = "test" ;
287
+ var value3 = "test" ;
288
+ await ( AssertTotalParametersAsync (
289
+ QueryMode . Update ,
290
+ db . Customers . Where ( c => c . CustomerId == value3 ) ,
291
+ x => new Customer { ContactName = value2 , CompanyName = value } ,
292
+ 3 ) ) ;
293
+ }
294
+
295
+ [ Test ]
296
+ public async Task UsingParameterInDMLDeleteTwiceAsync ( )
297
+ {
298
+ var value = "test" ;
299
+ await ( AssertTotalParametersAsync (
300
+ QueryMode . Delete ,
301
+ db . Customers . Where ( c => c . CustomerId == value && c . CompanyName == value ) ,
302
+ 2 ) ) ;
303
+ }
304
+
305
+ [ Test ]
306
+ public async Task UsingTwoParametersInDMLDeleteAsync ( )
307
+ {
308
+ var value = "test" ;
309
+ var value2 = "test" ;
310
+ await ( AssertTotalParametersAsync (
311
+ QueryMode . Delete ,
312
+ db . Customers . Where ( c => c . CustomerId == value && c . CompanyName == value2 ) ,
313
+ 2 ) ) ;
314
+ }
315
+
316
+ private async Task AssertTotalParametersAsync < T > ( IQueryable < T > query , int parameterNumber , int ? linqParameterNumber = null , CancellationToken cancellationToken = default ( CancellationToken ) )
217
317
{
218
318
using ( var sqlSpy = new SqlLogSpy ( ) )
219
319
{
320
+ // In case of arrays linqParameterNumber and parameterNumber will be different
321
+ Assert . That (
322
+ GetLinqExpression ( query ) . ParameterValuesByName . Count ,
323
+ Is . EqualTo ( linqParameterNumber ?? parameterNumber ) ,
324
+ "Linq expression has different number of parameters" ) ;
325
+
220
326
await ( query . ToListAsync ( cancellationToken ) ) ;
221
- var sqlParameters = sqlSpy . GetWholeLog ( ) . Split ( ';' ) [ 1 ] ;
222
- var matches = Regex . Matches ( sqlParameters , @"([\d\w]+)[\s]+\=" , RegexOptions . IgnoreCase ) ;
327
+ AssertParameters ( sqlSpy , parameterNumber ) ;
328
+ }
329
+ }
330
+
331
+ private static Task AssertTotalParametersAsync < T > ( QueryMode queryMode , IQueryable < T > query , int parameterNumber , CancellationToken cancellationToken = default ( CancellationToken ) )
332
+ {
333
+ return AssertTotalParametersAsync ( queryMode , query , null , parameterNumber , cancellationToken ) ;
334
+ }
335
+
336
+ private static async Task AssertTotalParametersAsync < T > ( QueryMode queryMode , IQueryable < T > query , Expression < Func < T , T > > expression , int parameterNumber , CancellationToken cancellationToken = default ( CancellationToken ) )
337
+ {
338
+ var provider = query . Provider as INhQueryProvider ;
339
+ Assert . That ( provider , Is . Not . Null ) ;
223
340
224
- // Due to ODBC drivers not supporting parameter names, we have to do a distinct of parameter names.
225
- var distinctParameters = matches . OfType < Match > ( ) . Select ( m => m . Groups [ 1 ] . Value . Trim ( ) ) . Distinct ( ) . ToList ( ) ;
226
- Assert . That ( distinctParameters , Has . Count . EqualTo ( parameterNumber ) ) ;
341
+ var dmlExpression = expression != null
342
+ ? DmlExpressionRewriter . PrepareExpression ( query . Expression , expression )
343
+ : query . Expression ;
344
+
345
+ using ( var sqlSpy = new SqlLogSpy ( ) )
346
+ {
347
+ Assert . That ( await ( provider . ExecuteDmlAsync < T > ( queryMode , dmlExpression , cancellationToken ) ) , Is . EqualTo ( 0 ) , "The DML query updated the data" ) ; // Avoid updating the data
348
+ AssertParameters ( sqlSpy , parameterNumber ) ;
227
349
}
228
350
}
351
+
352
+ private static void AssertParameters ( SqlLogSpy sqlSpy , int parameterNumber )
353
+ {
354
+ var sqlParameters = sqlSpy . GetWholeLog ( ) . Split ( ';' ) [ 1 ] ;
355
+ var matches = Regex . Matches ( sqlParameters , @"([\d\w]+)[\s]+\=" , RegexOptions . IgnoreCase ) ;
356
+
357
+ // Due to ODBC drivers not supporting parameter names, we have to do a distinct of parameter names.
358
+ var distinctParameters = matches . OfType < Match > ( ) . Select ( m => m . Groups [ 1 ] . Value . Trim ( ) ) . Distinct ( ) . ToList ( ) ;
359
+ Assert . That ( distinctParameters , Has . Count . EqualTo ( parameterNumber ) ) ;
360
+ }
361
+
362
+ private NhLinqExpression GetLinqExpression < T > ( QueryMode queryMode , IQueryable < T > query , Expression < Func < T , T > > expression )
363
+ {
364
+ return GetLinqExpression ( queryMode , DmlExpressionRewriter . PrepareExpression ( query . Expression , expression ) ) ;
365
+ }
366
+
367
+ private NhLinqExpression GetLinqExpression < T > ( QueryMode queryMode , IQueryable < T > query )
368
+ {
369
+ return GetLinqExpression ( queryMode , query . Expression ) ;
370
+ }
371
+
372
+ private NhLinqExpression GetLinqExpression < T > ( IQueryable < T > query )
373
+ {
374
+ return GetLinqExpression ( QueryMode . Select , query . Expression ) ;
375
+ }
376
+
377
+ private NhLinqExpression GetLinqExpression ( QueryMode queryMode , Expression expression )
378
+ {
379
+ return queryMode == QueryMode . Select
380
+ ? new NhLinqExpression ( expression , Sfi )
381
+ : new NhLinqDmlExpression < Customer > ( queryMode , expression , Sfi ) ;
382
+ }
229
383
}
230
384
}
0 commit comments