@@ -213,6 +213,351 @@ public async Task MultipleGetReadOnlyCollectionTestAsync()
213
213
}
214
214
}
215
215
216
+ [ Test ]
217
+ public async Task GetManyReadWriteTestAsync ( )
218
+ {
219
+ var persister = Sfi . GetEntityPersister ( typeof ( ReadWrite ) . FullName ) ;
220
+ Assert . That ( persister . Cache . Cache , Is . Not . Null ) ;
221
+ Assert . That ( persister . Cache . Cache , Is . TypeOf < BatchableCache > ( ) ) ;
222
+ int [ ] getIds ;
223
+ int [ ] loadIds ;
224
+
225
+ using ( var s = Sfi . OpenSession ( ) )
226
+ using ( var tx = s . BeginTransaction ( ) )
227
+ {
228
+ var items = await ( s . Query < ReadWrite > ( ) . ToListAsync ( ) ) ;
229
+ loadIds = getIds = items . OrderBy ( o => o . Id ) . Select ( o => o . Id ) . ToArray ( ) ;
230
+ await ( tx . CommitAsync ( ) ) ;
231
+ }
232
+
233
+ // Batch size 3
234
+ var parentTestCases = new List < Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > >
235
+ {
236
+ // When the cache is empty, GetMany will be called three times. First time in type
237
+ // DefaultLoadEventListener, the second time in BatchingEntityLoader and third in ReadWriteCache.
238
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
239
+ loadIds ,
240
+ 0 ,
241
+ new [ ]
242
+ {
243
+ new [ ] { 0 , 1 , 2 } , // Triggered by LoadFromSecondLevelCache method of DefaultLoadEventListener type
244
+ new [ ] { 1 , 2 , 3 } , // Triggered by Load method of BatchingEntityLoader type
245
+ new [ ] { 0 , 1 , 2 } // Triggered by PutMany method of ReadWriteCache type
246
+ } ,
247
+ new [ ] { 0 , 1 , 2 } ,
248
+ null
249
+ ) ,
250
+ // When there are not enough uninitialized entities after the demanded one to fill the batch,
251
+ // the nearest before the demanded entity are added.
252
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
253
+ loadIds ,
254
+ 4 ,
255
+ new [ ]
256
+ {
257
+ new [ ] { 4 , 5 , 3 } ,
258
+ new [ ] { 5 , 3 , 2 } ,
259
+ new [ ] { 4 , 5 , 3 } ,
260
+ } ,
261
+ new [ ] { 3 , 4 , 5 } ,
262
+ null
263
+ ) ,
264
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
265
+ loadIds ,
266
+ 5 ,
267
+ new [ ]
268
+ {
269
+ new [ ] { 5 , 4 , 3 } ,
270
+ new [ ] { 4 , 3 , 2 } ,
271
+ new [ ] { 5 , 4 , 3 } ,
272
+ } ,
273
+ new [ ] { 3 , 4 , 5 } ,
274
+ null
275
+ ) ,
276
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
277
+ loadIds ,
278
+ 0 ,
279
+ new [ ]
280
+ {
281
+ new [ ] { 0 , 1 , 2 } // 0 get assembled and no further processing is done
282
+ } ,
283
+ null ,
284
+ ( i ) => i % 2 == 0 // Cache all even indexes before loading
285
+ ) ,
286
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
287
+ loadIds ,
288
+ 1 ,
289
+ new [ ]
290
+ {
291
+ new [ ] { 1 , 2 , 3 } , // 2 gets assembled inside LoadFromSecondLevelCache
292
+ new [ ] { 3 , 4 , 5 } ,
293
+ new [ ] { 1 , 3 , 5 }
294
+ } ,
295
+ new [ ] { 1 , 3 , 5 } ,
296
+ ( i ) => i % 2 == 0
297
+ ) ,
298
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
299
+ loadIds ,
300
+ 5 ,
301
+ new [ ]
302
+ {
303
+ new [ ] { 5 , 4 , 3 } , // 4 gets assembled inside LoadFromSecondLevelCache
304
+ new [ ] { 3 , 2 , 1 } ,
305
+ new [ ] { 1 , 3 , 5 }
306
+ } ,
307
+ new [ ] { 1 , 3 , 5 } ,
308
+ ( i ) => i % 2 == 0
309
+ ) ,
310
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
311
+ loadIds ,
312
+ 0 ,
313
+ new [ ]
314
+ {
315
+ new [ ] { 0 , 1 , 2 } , // 1 gets assembled inside LoadFromSecondLevelCache
316
+ new [ ] { 2 , 3 , 4 } ,
317
+ new [ ] { 0 , 2 , 4 }
318
+ } ,
319
+ new [ ] { 0 , 2 , 4 } ,
320
+ ( i ) => i % 2 != 0
321
+ ) ,
322
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
323
+ loadIds ,
324
+ 4 ,
325
+ new [ ]
326
+ {
327
+ new [ ] { 4 , 5 , 3 } , // 5 and 3 get assembled inside LoadFromSecondLevelCache
328
+ new [ ] { 2 , 1 , 0 } ,
329
+ new [ ] { 0 , 2 , 4 }
330
+ } ,
331
+ new [ ] { 0 , 2 , 4 } ,
332
+ ( i ) => i % 2 != 0
333
+ ) ,
334
+ // Tests by loading different ids
335
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
336
+ loadIds . Where ( ( v , i ) => i != 0 ) . ToArray ( ) ,
337
+ 0 ,
338
+ new [ ]
339
+ {
340
+ new [ ] { 0 , 5 , 4 } , // Triggered by LoadFromSecondLevelCache method of DefaultLoadEventListener type
341
+ new [ ] { 3 , 4 , 5 } , // Triggered by Load method of BatchingEntityLoader type
342
+ new [ ] { 0 , 4 , 5 } , // Triggered by PutMany method of ReadWriteCache type
343
+ } ,
344
+ new [ ] { 0 , 4 , 5 } ,
345
+ null
346
+ ) ,
347
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
348
+ loadIds . Where ( ( v , i ) => i != 4 ) . ToArray ( ) ,
349
+ 4 ,
350
+ new [ ]
351
+ {
352
+ new [ ] { 4 , 5 , 3 } ,
353
+ new [ ] { 5 , 3 , 2 } ,
354
+ new [ ] { 3 , 4 , 5 }
355
+ } ,
356
+ new [ ] { 3 , 4 , 5 } ,
357
+ null
358
+ ) ,
359
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
360
+ loadIds . Where ( ( v , i ) => i != 0 ) . ToArray ( ) ,
361
+ 0 ,
362
+ new [ ]
363
+ {
364
+ new [ ] { 0 , 5 , 4 } // 0 get assembled and no further processing is done
365
+ } ,
366
+ null ,
367
+ ( i ) => i % 2 == 0 // Cache all even indexes before loading
368
+ ) ,
369
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
370
+ loadIds . Where ( ( v , i ) => i != 1 ) . ToArray ( ) ,
371
+ 1 ,
372
+ new [ ]
373
+ {
374
+ new [ ] { 1 , 5 , 4 } , // 4 gets assembled inside LoadFromSecondLevelCache
375
+ new [ ] { 5 , 3 , 2 } ,
376
+ new [ ] { 1 , 3 , 5 }
377
+ } ,
378
+ new [ ] { 1 , 3 , 5 } ,
379
+ ( i ) => i % 2 == 0
380
+ )
381
+ } ;
382
+
383
+ foreach ( var tuple in parentTestCases )
384
+ {
385
+ await ( AssertMultipleCacheCallsAsync < ReadWrite > ( tuple . Item1 , getIds , tuple . Item2 , tuple . Item3 , tuple . Item4 , tuple . Item5 ) ) ;
386
+ }
387
+ }
388
+
389
+ [ Test ]
390
+ public async Task GetManyReadWriteItemTestAsync ( )
391
+ {
392
+ var persister = Sfi . GetEntityPersister ( typeof ( ReadWriteItem ) . FullName ) ;
393
+ Assert . That ( persister . Cache . Cache , Is . Not . Null ) ;
394
+ Assert . That ( persister . Cache . Cache , Is . TypeOf < BatchableCache > ( ) ) ;
395
+ int [ ] getIds ;
396
+ int [ ] loadIds ;
397
+
398
+ using ( var s = Sfi . OpenSession ( ) )
399
+ using ( var tx = s . BeginTransaction ( ) )
400
+ {
401
+ var items = await ( s . Query < ReadWriteItem > ( ) . Take ( 6 ) . ToListAsync ( ) ) ;
402
+ loadIds = getIds = items . OrderBy ( o => o . Id ) . Select ( o => o . Id ) . ToArray ( ) ;
403
+ await ( tx . CommitAsync ( ) ) ;
404
+ }
405
+ // Batch size 4
406
+ var parentTestCases = new List < Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > >
407
+ {
408
+ // When the cache is empty, GetMany will be called three times. First time in type
409
+ // DefaultLoadEventListener, the second time in BatchingEntityLoader and third in ReadWriteCache.
410
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
411
+ loadIds ,
412
+ 0 ,
413
+ new [ ]
414
+ {
415
+ new [ ] { 0 , 1 , 2 , 3 } , // Triggered by LoadFromSecondLevelCache method of DefaultLoadEventListener type
416
+ new [ ] { 1 , 2 , 3 , 4 } , // Triggered by Load method of BatchingEntityLoader type
417
+ new [ ] { 0 , 1 , 2 , 3 } // Triggered by PutMany method of ReadWriteCache type
418
+ } ,
419
+ new [ ] { 0 , 1 , 2 , 3 } ,
420
+ null
421
+ ) ,
422
+ // When there are not enough uninitialized entities after the demanded one to fill the batch,
423
+ // the nearest before the demanded entity are added.
424
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
425
+ loadIds ,
426
+ 4 ,
427
+ new [ ]
428
+ {
429
+ new [ ] { 4 , 5 , 3 , 2 } ,
430
+ new [ ] { 5 , 3 , 2 , 1 } ,
431
+ new [ ] { 4 , 5 , 3 , 2 }
432
+ } ,
433
+ new [ ] { 2 , 3 , 4 , 5 } ,
434
+ null
435
+ ) ,
436
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
437
+ loadIds ,
438
+ 5 ,
439
+ new [ ]
440
+ {
441
+ new [ ] { 5 , 4 , 3 , 2 } ,
442
+ new [ ] { 4 , 3 , 2 , 1 } ,
443
+ new [ ] { 5 , 4 , 3 , 2 }
444
+ } ,
445
+ new [ ] { 2 , 3 , 4 , 5 } ,
446
+ null
447
+ ) ,
448
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
449
+ loadIds ,
450
+ 0 ,
451
+ new [ ]
452
+ {
453
+ new [ ] { 0 , 1 , 2 , 3 } // 0 get assembled and no further processing is done
454
+ } ,
455
+ null ,
456
+ ( i ) => i % 2 == 0 // Cache all even indexes before loading
457
+ ) ,
458
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
459
+ loadIds ,
460
+ 1 ,
461
+ new [ ]
462
+ {
463
+ new [ ] { 1 , 2 , 3 , 4 } , // 2 and 4 get assembled inside LoadFromSecondLevelCache
464
+ new [ ] { 3 , 5 , 0 } ,
465
+ new [ ] { 1 , 3 , 5 }
466
+ } ,
467
+ new [ ] { 1 , 3 , 5 } ,
468
+ ( i ) => i % 2 == 0
469
+ ) ,
470
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
471
+ loadIds ,
472
+ 5 ,
473
+ new [ ]
474
+ {
475
+ new [ ] { 5 , 4 , 3 , 2 } , // 4 and 2 get assembled inside LoadFromSecondLevelCache
476
+ new [ ] { 3 , 1 , 0 } ,
477
+ new [ ] { 1 , 3 , 5 }
478
+ } ,
479
+ new [ ] { 1 , 3 , 5 } ,
480
+ ( i ) => i % 2 == 0
481
+ ) ,
482
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
483
+ loadIds ,
484
+ 0 ,
485
+ new [ ]
486
+ {
487
+ new [ ] { 0 , 1 , 2 , 3 } , // 1 and 3 get assembled inside LoadFromSecondLevelCache
488
+ new [ ] { 2 , 4 , 5 } ,
489
+ new [ ] { 0 , 2 , 4 }
490
+ } ,
491
+ new [ ] { 0 , 2 , 4 } ,
492
+ ( i ) => i % 2 != 0
493
+ ) ,
494
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
495
+ loadIds ,
496
+ 4 ,
497
+ new [ ]
498
+ {
499
+ new [ ] { 4 , 5 , 3 , 2 } , // 5 and 3 get assembled inside LoadFromSecondLevelCache
500
+ new [ ] { 2 , 1 , 0 } ,
501
+ new [ ] { 0 , 2 , 4 }
502
+ } ,
503
+ new [ ] { 0 , 2 , 4 } ,
504
+ ( i ) => i % 2 != 0
505
+ ) ,
506
+ // Tests by loading different ids
507
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
508
+ loadIds . Where ( ( v , i ) => i != 0 ) . ToArray ( ) ,
509
+ 0 ,
510
+ new [ ]
511
+ {
512
+ new [ ] { 0 , 5 , 4 , 3 } , // Triggered by LoadFromSecondLevelCache method of DefaultLoadEventListener type
513
+ new [ ] { 5 , 4 , 3 , 2 } , // Triggered by Load method of BatchingEntityLoader type
514
+ new [ ] { 0 , 5 , 4 , 3 } , // Triggered by PutMany method of ReadWriteCache type
515
+ } ,
516
+ new [ ] { 0 , 5 , 4 , 3 } ,
517
+ null
518
+ ) ,
519
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
520
+ loadIds . Where ( ( v , i ) => i != 5 ) . ToArray ( ) ,
521
+ 5 ,
522
+ new [ ]
523
+ {
524
+ new [ ] { 5 , 4 , 3 , 2 } ,
525
+ new [ ] { 4 , 3 , 2 , 1 } ,
526
+ new [ ] { 2 , 3 , 4 , 5 }
527
+ } ,
528
+ new [ ] { 2 , 3 , 4 , 5 } ,
529
+ null
530
+ ) ,
531
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
532
+ loadIds . Where ( ( v , i ) => i != 0 ) . ToArray ( ) ,
533
+ 0 ,
534
+ new [ ]
535
+ {
536
+ new [ ] { 0 , 5 , 4 , 3 } // 0 get assembled and no further processing is done
537
+ } ,
538
+ null ,
539
+ ( i ) => i % 2 == 0 // Cache all even indexes before loading
540
+ ) ,
541
+ new Tuple < int [ ] , int , int [ ] [ ] , int [ ] , Func < int , bool > > (
542
+ loadIds . Where ( ( v , i ) => i != 1 ) . ToArray ( ) ,
543
+ 1 ,
544
+ new [ ]
545
+ {
546
+ new [ ] { 1 , 5 , 4 , 3 } , // 4 get assembled inside LoadFromSecondLevelCache
547
+ new [ ] { 5 , 3 , 2 , 0 } ,
548
+ new [ ] { 1 , 3 , 5 }
549
+ } ,
550
+ new [ ] { 1 , 3 , 5 } ,
551
+ ( i ) => i % 2 == 0
552
+ ) ,
553
+ } ;
554
+
555
+ foreach ( var tuple in parentTestCases )
556
+ {
557
+ await ( AssertMultipleCacheCallsAsync < ReadWriteItem > ( tuple . Item1 , getIds , tuple . Item2 , tuple . Item3 , tuple . Item4 , tuple . Item5 ) ) ;
558
+ }
559
+ }
560
+
216
561
[ Test ]
217
562
public async Task MultipleGetReadOnlyTestAsync ( )
218
563
{
0 commit comments