8
8
//------------------------------------------------------------------------------
9
9
10
10
11
+ using System . Linq ;
11
12
using System . Text . RegularExpressions ;
12
13
using NHibernate . Cfg . MappingSchema ;
13
14
using NHibernate . Mapping . ByCode ;
14
15
using NHibernate . Test . Hql . EntityJoinHqlTestEntities ;
15
16
using NUnit . Framework ;
17
+ using NHibernate . Linq ;
16
18
17
19
namespace NHibernate . Test . Hql
18
20
{
@@ -164,12 +166,12 @@ public async Task EntityJoinWithNullableOneToOneEntityComparisonInWithClausShoul
164
166
. CreateQuery (
165
167
"select ex "
166
168
+ "from NullableOwner ex "
167
- + "left join OneToOneEntity st with st = ex.OneToOne "
168
- ) . SetMaxResults ( 1 )
169
+ + "inner join OneToOneEntity st with st = ex.OneToOne "
170
+ )
169
171
. UniqueResultAsync < NullableOwner > ( ) ) ;
170
172
171
- Assert . That ( Regex . Matches ( sqlLog . GetWholeLog ( ) , "OneToOneEntity" ) . Count , Is . EqualTo ( 2 ) ) ;
172
- Assert . That ( sqlLog . Appender . GetEvents ( ) . Length , Is . EqualTo ( 1 ) , "Only one SQL select is expected" ) ;
173
+ Assert . That ( entity , Is . Not . Null ) ;
174
+ Assert . That ( Regex . Matches ( sqlLog . Appender . GetEvents ( ) [ 0 ] . RenderedMessage , "OneToOneEntity" ) . Count , Is . EqualTo ( 2 ) ) ;
173
175
}
174
176
}
175
177
@@ -188,8 +190,28 @@ public async Task NullableOneToOneWhereEntityIsNotNullAsync()
188
190
) . SetMaxResults ( 1 )
189
191
. UniqueResultAsync < NullableOwner > ( ) ) ;
190
192
191
- Assert . That ( Regex . Matches ( sqlLog . GetWholeLog ( ) , "OneToOneEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
192
- Assert . That ( sqlLog . Appender . GetEvents ( ) . Length , Is . EqualTo ( 1 ) , "Only one SQL select is expected" ) ;
193
+ Assert . That ( entity , Is . Not . Null ) ;
194
+ Assert . That ( Regex . Matches ( sqlLog . Appender . GetEvents ( ) [ 0 ] . RenderedMessage , "OneToOneEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
195
+ }
196
+ }
197
+
198
+ [ Test ]
199
+ public async Task NullableOneToOneWhereEntityIsNullAsync ( )
200
+ {
201
+ using ( var sqlLog = new SqlLogSpy ( ) )
202
+ using ( var session = OpenSession ( ) )
203
+ {
204
+ var entity =
205
+ await ( session
206
+ . CreateQuery (
207
+ "select ex "
208
+ + "from NullableOwner ex "
209
+ + "where ex.OneToOne is null "
210
+ ) . SetMaxResults ( 1 )
211
+ . UniqueResultAsync < NullableOwner > ( ) ) ;
212
+
213
+ Assert . That ( entity , Is . Not . Null ) ;
214
+ Assert . That ( Regex . Matches ( sqlLog . Appender . GetEvents ( ) [ 0 ] . RenderedMessage , "OneToOneEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
193
215
}
194
216
}
195
217
@@ -208,8 +230,8 @@ public async Task NullableOneToOneWhereIdIsNotNullAsync()
208
230
) . SetMaxResults ( 1 )
209
231
. UniqueResultAsync < NullableOwner > ( ) ) ;
210
232
211
- Assert . That ( Regex . Matches ( sqlLog . GetWholeLog ( ) , "OneToOneEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
212
- Assert . That ( sqlLog . Appender . GetEvents ( ) . Length , Is . EqualTo ( 1 ) , "Only one SQL select is expected" ) ;
233
+ Assert . That ( entity , Is . Not . Null ) ;
234
+ Assert . That ( Regex . Matches ( sqlLog . Appender . GetEvents ( ) [ 0 ] . RenderedMessage , "OneToOneEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
213
235
}
214
236
}
215
237
@@ -222,14 +244,32 @@ public async Task NullablePropRefWhereIdEntityNotNullShouldAddJoinAsync()
222
244
var entity =
223
245
await ( session
224
246
. CreateQuery (
225
- "select ex "
226
- + "from NullableOwner ex "
247
+ "select ex from NullableOwner ex "
227
248
+ "where ex.PropRef is not null "
228
- ) . SetMaxResults ( 1 )
249
+ )
229
250
. UniqueResultAsync < NullableOwner > ( ) ) ;
230
251
231
- Assert . That ( Regex . Matches ( sqlLog . GetWholeLog ( ) , "PropRefEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
232
- Assert . That ( sqlLog . Appender . GetEvents ( ) . Length , Is . EqualTo ( 1 ) , "Only one SQL select is expected" ) ;
252
+ Assert . That ( entity , Is . Not . Null ) ;
253
+ Assert . That ( Regex . Matches ( sqlLog . Appender . GetEvents ( ) [ 0 ] . RenderedMessage , "PropRefEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
254
+ }
255
+ }
256
+
257
+ [ Test ]
258
+ public async Task NullablePropRefWhereIdEntityNullShouldAddJoinAsync ( )
259
+ {
260
+ using ( var sqlLog = new SqlLogSpy ( ) )
261
+ using ( var session = OpenSession ( ) )
262
+ {
263
+ var entity =
264
+ await ( session
265
+ . CreateQuery (
266
+ "select ex from NullableOwner ex "
267
+ + "where ex.PropRef is null "
268
+ )
269
+ . UniqueResultAsync < NullableOwner > ( ) ) ;
270
+
271
+ Assert . That ( entity , Is . Not . Null ) ;
272
+ Assert . That ( Regex . Matches ( sqlLog . Appender . GetEvents ( ) [ 0 ] . RenderedMessage , "PropRefEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
233
273
}
234
274
}
235
275
@@ -245,28 +285,41 @@ public async Task NullableOneToOneFetchQueryIsNotAffectedAsync()
245
285
"select ex "
246
286
+ "from NullableOwner ex left join fetch ex.OneToOne o "
247
287
+ "where o is null "
248
- ) . SetMaxResults ( 1 )
288
+ )
249
289
. UniqueResultAsync < NullableOwner > ( ) ) ;
250
290
291
+ Assert . That ( entity , Is . Not . Null ) ;
251
292
Assert . That ( Regex . Matches ( sqlLog . GetWholeLog ( ) , "OneToOneEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
252
293
}
253
294
}
254
-
295
+
296
+ [ Test ( Description = "GH-2611" ) ]
297
+ public async Task NullableOneIsNullLinqAsync ( )
298
+ {
299
+ using ( var session = OpenSession ( ) )
300
+ {
301
+ var entity = await ( session . Query < NullableOwner > ( ) . Where ( x => x . OneToOne == null ) . FirstOrDefaultAsync ( ) ) ;
302
+ Assert . That ( entity , Is . Not . Null ) ;
303
+ }
304
+ }
305
+
255
306
[ Test ]
256
307
public async Task NullableOneToOneFetchQueryIsNotAffected2Async ( )
257
308
{
258
309
using ( var sqlLog = new SqlLogSpy ( ) )
259
310
using ( var session = OpenSession ( ) )
260
311
{
261
- var entity =
312
+ var entities =
262
313
await ( session
263
314
. CreateQuery (
264
315
"select ex "
265
316
+ "from NullableOwner ex left join fetch ex.OneToOne o "
266
317
+ "where o.Id is null "
267
- ) . SetMaxResults ( 1 )
268
- . UniqueResultAsync < NullableOwner > ( ) ) ;
318
+ )
319
+ . ListAsync < NullableOwner > ( ) ) ;
320
+ var entity = entities [ 0 ] ;
269
321
322
+ Assert . That ( entity , Is . Not . Null ) ;
270
323
Assert . That ( Regex . Matches ( sqlLog . GetWholeLog ( ) , "OneToOneEntity" ) . Count , Is . EqualTo ( 1 ) ) ;
271
324
}
272
325
}
@@ -488,8 +541,9 @@ protected override HbmMapping GetMappings()
488
541
mapper . Class < OneToOneEntity > (
489
542
rc =>
490
543
{
491
- rc . Id ( e => e . Id , m => m . Generator ( Generators . GuidComb ) ) ;
544
+ rc . Id ( e => e . Id , m => m . Generator ( Generators . Foreign < OneToOneEntity > ( x => x . Parent ) ) ) ;
492
545
rc . Property ( e => e . Name ) ;
546
+ rc . OneToOne ( x => x . Parent , x => x . Constrained ( true ) ) ;
493
547
} ) ;
494
548
495
549
mapper . Class < PropRefEntity > (
@@ -505,7 +559,11 @@ protected override HbmMapping GetMappings()
505
559
{
506
560
rc . Id ( e => e . Id , m => m . Generator ( Generators . GuidComb ) ) ;
507
561
rc . Property ( e => e . Name ) ;
508
- rc . OneToOne ( e => e . OneToOne , m => m . Constrained ( false ) ) ;
562
+ rc . OneToOne ( e => e . OneToOne , m =>
563
+ {
564
+ m . Constrained ( false ) ;
565
+ m . Cascade ( Mapping . ByCode . Cascade . All ) ;
566
+ } ) ;
509
567
rc . ManyToOne (
510
568
e => e . PropRef ,
511
569
m =>
@@ -514,6 +572,7 @@ protected override HbmMapping GetMappings()
514
572
m . PropertyRef ( nameof ( PropRefEntity . PropertyRef ) ) ;
515
573
m . ForeignKey ( "none" ) ;
516
574
m . NotFound ( NotFoundMode . Ignore ) ;
575
+ m . Cascade ( Mapping . ByCode . Cascade . All ) ;
517
576
} ) ;
518
577
} ) ;
519
578
@@ -584,7 +643,10 @@ protected override void OnSetUp()
584
643
} ;
585
644
session . Save ( _noAssociation ) ;
586
645
587
- session . Flush ( ) ;
646
+ session . Save ( new NullableOwner ( ) { Name = "NoAssociation" } ) ;
647
+ var nullableOwner = new NullableOwner ( ) { Name = "Association" , PropRef = new PropRefEntity ( ) { Name = "x" , PropertyRef = "xx" } , OneToOne = new OneToOneEntity ( ) { Name = "x" } , } ;
648
+ nullableOwner . OneToOne . Parent = nullableOwner ;
649
+ session . Save ( nullableOwner ) ;
588
650
transaction . Commit ( ) ;
589
651
}
590
652
}
0 commit comments