44using System . Linq . Expressions ;
55using JsonApiDotNetCore . Abstractions ;
66using System . Reflection ;
7+ using JsonApiDotNetCore . Extensions ;
78using JsonApiDotNetCore . Routing ;
89using Microsoft . EntityFrameworkCore ;
910
@@ -28,32 +29,53 @@ public object Get(string id)
2829 var relationalRoute = _context . Route as RelationalRoute ;
2930 if ( relationalRoute == null )
3031 {
31- return GetEntityById ( id ) ;
32+ return GetEntityById ( _context . Route . BaseModelType , id , null ) ;
3233 }
33- return GetRelated ( id , relationalRoute . RelationshipName ) ;
34+ return GetRelated ( id , relationalRoute ) ;
3435 }
3536
36- private object GetRelated ( string id , string relationshipName )
37+ private object GetRelated ( string id , RelationalRoute relationalRoute )
3738 {
3839 // HACK: this would rely on lazy loading to work...will probably fail
39- var entity = GetEntityById ( id ) ;
40- var entityType = entity . GetType ( ) ;
41- return entityType . GetProperties ( ) . FirstOrDefault ( pi => pi . Name == relationshipName ) . GetValue ( entity ) ;
40+ var entity = GetEntityById ( relationalRoute . RelationalType , id , relationalRoute . RelationshipName ) ;
41+ return relationalRoute . RelationalType . GetProperties ( ) . FirstOrDefault ( pi => pi . Name . ToCamelCase ( ) == relationalRoute . RelationshipName . ToCamelCase ( ) ) . GetValue ( entity ) ;
4242 }
4343
44- private object GetDbSetFromContext ( string propName )
44+
45+ private IQueryable GetDbSetFromContext ( string propName )
4546 {
4647 var dbContext = _context . DbContext ;
47- return dbContext . GetType ( ) . GetProperties ( ) . FirstOrDefault ( pI => pI . Name == propName ) ? . GetValue ( dbContext , null ) ;
48+ return ( IQueryable ) dbContext . GetType ( ) . GetProperties ( ) . FirstOrDefault ( pI => pI . Name . ToCamelCase ( ) == propName ) ? . GetValue ( dbContext , null ) ;
4849 }
4950
50- private object GetEntityById ( string id )
51+ private object GetEntityById ( Type modelType , string id , string includedRelationship )
5152 {
5253 // HACK: I _believe_ by casting to IEnumerable, we are loading all records into memory, if so... find a better way...
5354 // Also, we are making a BIG assumption that the resource has an attribute Id and not ResourceId which is allowed by EF
54- return
55- ( GetDbSetFromContext ( _context . Route . BaseRouteDefinition . ContextPropertyName ) as IEnumerable < dynamic > ) ?
56- . FirstOrDefault ( x => x . Id . ToString ( ) == id ) ;
55+ var methodToCall = typeof ( ResourceRepository ) . GetMethods ( ) . Single ( method => method . Name . Equals ( "GetDbSet" ) ) ;
56+ var genericMethod = methodToCall . MakeGenericMethod ( modelType ) ;
57+ genericMethod . Invoke ( genericMethod , null ) ;
58+ var dbSet = genericMethod . Invoke ( this , null ) ;
59+
60+ if ( ! string . IsNullOrEmpty ( includedRelationship ) )
61+ {
62+ var includeMethod = typeof ( ResourceRepository ) . GetMethods ( ) . Single ( method => method . Name . Equals ( "IncludeEntity" ) ) ;
63+ var genericIncludeMethod = includeMethod . MakeGenericMethod ( modelType ) ;
64+ genericIncludeMethod . Invoke ( genericMethod , null ) ;
65+ dbSet = genericIncludeMethod . Invoke ( this , new [ ] { dbSet , includedRelationship } ) ;
66+ }
67+
68+ return ( dbSet as IEnumerable < dynamic > ) . SingleOrDefault ( x => x . Id . ToString ( ) == id ) ;
69+ }
70+
71+ private DbSet < T > GetDbSet < T > ( ) where T : class
72+ {
73+ return ( ( DbContext ) _context . DbContext ) . Set < T > ( ) ;
74+ }
75+
76+ private IQueryable < T > IncludeEntity < T > ( IQueryable < T > queryable , string includedEntityName ) where T : class
77+ {
78+ return queryable . Include ( includedEntityName ) ;
5779 }
5880 }
5981}
0 commit comments