@@ -371,6 +371,62 @@ from lead in ls.DefaultIfEmpty()
371371 }
372372 }
373373
374+ [ Fact ]
375+ public void TestNotAnyJoin ( )
376+ {
377+ // Test NotAny join operator - should return contacts that do NOT have any associated leads
378+ var query = new QueryExpression ( "contact" )
379+ {
380+ ColumnSet = new ColumnSet ( "contactid" , "lastname" )
381+ } ;
382+
383+ var linkEntity = new LinkEntity ( )
384+ {
385+ LinkToEntityName = "lead" ,
386+ LinkToAttributeName = "parentcontactid" ,
387+ LinkFromEntityName = "contact" ,
388+ LinkFromAttributeName = "contactid" ,
389+ Columns = new ColumnSet ( false ) ,
390+ EntityAlias = "lead" ,
391+ JoinOperator = JoinOperator . NotAny ,
392+ } ;
393+
394+ query . LinkEntities . Add ( linkEntity ) ;
395+
396+ var result = orgAdminService . RetrieveMultiple ( query ) . Entities . Cast < Contact > ( ) . ToList ( ) ;
397+
398+ // Should return contact3 and contact4 since they have no associated leads
399+ Assert . Equal ( 2 , result . Count ) ;
400+ Assert . Contains ( result , x => x . Id == contact3 . Id ) ;
401+ Assert . Contains ( result , x => x . Id == contact4 . Id ) ;
402+ Assert . DoesNotContain ( result , x => x . Id == contact1 . Id ) ;
403+ Assert . DoesNotContain ( result , x => x . Id == contact2 . Id ) ;
404+ }
405+
406+ [ Fact ]
407+ public void TestNotAnyJoinFetchXml ( )
408+ {
409+ // Test NotAny join operator via FetchXML - should return contacts that do NOT have any associated leads
410+ var fetchXml = @"
411+ <fetch>
412+ <entity name='contact'>
413+ <attribute name='contactid' />
414+ <attribute name='lastname' />
415+ <link-entity name='lead' from='parentcontactid' to='contactid' link-type='notany' />
416+ </entity>
417+ </fetch>" ;
418+
419+ var fetchExpr = new FetchExpression ( fetchXml ) ;
420+ var result = orgAdminService . RetrieveMultiple ( fetchExpr ) . Entities . Cast < Contact > ( ) . ToList ( ) ;
421+
422+ // Should return contact3 and contact4 since they have no associated leads
423+ Assert . Equal ( 2 , result . Count ) ;
424+ Assert . Contains ( result , x => x . Id == contact3 . Id ) ;
425+ Assert . Contains ( result , x => x . Id == contact4 . Id ) ;
426+ Assert . DoesNotContain ( result , x => x . Id == contact1 . Id ) ;
427+ Assert . DoesNotContain ( result , x => x . Id == contact2 . Id ) ;
428+ }
429+
374430 [ Fact ]
375431 public void TestNestedJoins ( )
376432 {
0 commit comments