44using System . Linq ;
55using Dapper ;
66using System . Threading . Tasks ;
7+ using System . Dynamic ;
78
89namespace SqlKata . Execution
910{
@@ -15,11 +16,52 @@ public static async Task<IEnumerable<T>> GetAsync<T>(this QueryFactory db, Query
1516 {
1617 var compiled = db . Compile ( query ) ;
1718
18- return await db . Connection . QueryAsync < T > (
19+ var result = ( await db . Connection . QueryAsync < T > (
1920 compiled . Sql ,
2021 compiled . NamedBindings ,
2122 commandTimeout : db . QueryTimeout
22- ) ;
23+ ) ) . ToList ( ) ;
24+
25+ if ( ! result . Any ( ) )
26+ {
27+ return result ;
28+ }
29+
30+ if ( result [ 0 ] is IDynamicMetaObjectProvider )
31+ {
32+ var dynamicResult = result
33+ . Cast < IDictionary < string , object > > ( )
34+ . Select ( x => new Dictionary < string , object > ( x , StringComparer . OrdinalIgnoreCase ) )
35+ . ToList ( ) ;
36+
37+ foreach ( var include in query . Includes )
38+ {
39+ var ids = dynamicResult . Where ( x => x [ include . ForeignKey ] != null )
40+ . Select ( x => x [ include . ForeignKey ] . ToString ( ) )
41+ . ToList ( ) ;
42+
43+ if ( ! ids . Any ( ) )
44+ {
45+ continue ;
46+ }
47+
48+ var related = ( await include . Query . WhereIn ( include . LocalKey , ids ) . GetAsync ( ) )
49+ . Cast < IDictionary < string , object > > ( )
50+ . Select ( x => new Dictionary < string , object > ( x , StringComparer . OrdinalIgnoreCase ) )
51+ . ToDictionary ( x => x [ include . LocalKey ] . ToString ( ) ) ;
52+
53+ foreach ( var item in dynamicResult )
54+ {
55+ var foreignValue = item [ include . ForeignKey ] . ToString ( ) ;
56+ item [ include . Name ] = related . ContainsKey ( foreignValue ) ? related [ foreignValue ] : null ;
57+ }
58+ }
59+
60+ return dynamicResult . Cast < T > ( ) ;
61+
62+ }
63+
64+ return result ;
2365 }
2466
2567 public static async Task < IEnumerable < IDictionary < string , object > > > GetDictionaryAsync ( this QueryFactory db , Query query )
@@ -40,36 +82,33 @@ public static async Task<IEnumerable<dynamic>> GetAsync(this QueryFactory db, Qu
4082 return await GetAsync < dynamic > ( db , query ) ;
4183 }
4284
43- public static async Task < T > FirstAsync < T > ( this QueryFactory db , Query query )
85+ public static async Task < T > FirstOrDefaultAsync < T > ( this QueryFactory db , Query query )
4486 {
45- var compiled = db . Compile ( query . Limit ( 1 ) ) ;
87+ var list = await GetAsync ( db , query . Limit ( 1 ) ) ;
4688
47- return await db . Connection . QueryFirstAsync < T > (
48- compiled . Sql ,
49- compiled . NamedBindings ,
50- commandTimeout : db . QueryTimeout
51- ) ;
89+ return list . ElementAtOrDefault ( 0 ) ;
5290 }
5391
54- public static async Task < dynamic > FirstAsync ( this QueryFactory db , Query query )
92+ public static async Task < dynamic > FirstOrDefaultAsync ( this QueryFactory db , Query query )
5593 {
56- return await FirstAsync < dynamic > ( db , query ) ;
94+ return await FirstOrDefaultAsync < dynamic > ( db , query ) ;
5795 }
5896
59- public static async Task < T > FirstOrDefaultAsync < T > ( this QueryFactory db , Query query )
97+ public static async Task < T > FirstAsync < T > ( this QueryFactory db , Query query )
6098 {
61- var compiled = db . Compile ( query . Limit ( 1 ) ) ;
99+ var item = await FirstOrDefaultAsync < T > ( db , query ) ;
62100
63- return await db . Connection . QueryFirstOrDefaultAsync < T > (
64- compiled . Sql ,
65- compiled . NamedBindings ,
66- commandTimeout : db . QueryTimeout
67- ) ;
101+ if ( item == null )
102+ {
103+ throw new InvalidOperationException ( "The sequence contains no elements" ) ;
104+ }
105+
106+ return item ;
68107 }
69108
70- public static async Task < dynamic > FirstOrDefaultAsync ( this QueryFactory db , Query query )
109+ public static async Task < dynamic > FirstAsync ( this QueryFactory db , Query query )
71110 {
72- return await FirstOrDefaultAsync < dynamic > ( db , query ) ;
111+ return await FirstAsync < dynamic > ( db , query ) ;
73112 }
74113
75114 public static async Task < int > ExecuteAsync (
0 commit comments