1- using System ;
2- using System . Collections ;
3- using System . Collections . Generic ;
4- using System . Linq ;
5- using System . Reflection ;
6- using System . Threading . Tasks ;
71using AutoMapper ;
82using JsonApiDotNetCore . Data ;
9- using JsonApiDotNetCore . Extensions ;
103using JsonApiDotNetCore . Internal ;
114using JsonApiDotNetCore . Models ;
125using Microsoft . Extensions . Logging ;
6+ using System ;
7+ using System . Collections . Generic ;
8+ using System . Linq ;
9+ using System . Threading . Tasks ;
1310
1411namespace JsonApiDotNetCore . Services
1512{
16- public class MappingResourceService < TResource , TEntity >
17- : MappingResourceService < TResource , TEntity , int > ,
13+ public class DefaultResourceService < TResource > : DefaultResourceService < TResource , int > ,
1814 IResourceService < TResource >
1915 where TResource : class , IIdentifiable < int >
20- where TEntity : class , IIdentifiable < int >
2116 {
22- public MappingResourceService (
23- IJsonApiContext jsonApiContext ,
24- IEntityRepository < TEntity > entityRepository ,
25- ILoggerFactory loggerFactory ,
26- IMapper mapper )
27- : base ( jsonApiContext , entityRepository , loggerFactory , mapper )
17+ public DefaultResourceService (
18+ IJsonApiContext jsonApiContext ,
19+ IEntityRepository < TResource > entityRepository ,
20+ ILoggerFactory loggerFactory ) :
21+ base ( jsonApiContext , entityRepository , loggerFactory )
22+ { }
23+ }
24+
25+ public class DefaultResourceService < TResource , TId > : DefaultResourceService < TResource , TResource , TId > ,
26+ IResourceService < TResource , TId >
27+ where TResource : class , IIdentifiable < TId >
28+ {
29+ public DefaultResourceService (
30+ IJsonApiContext jsonApiContext ,
31+ IEntityRepository < TResource , TId > entityRepository ,
32+ ILoggerFactory loggerFactory ) :
33+ base ( jsonApiContext , entityRepository , loggerFactory )
2834 { }
2935 }
3036
31- public class MappingResourceService < TResource , TEntity , TId >
32- : IResourceService < TResource , TId >
37+ public class DefaultResourceService < TResource , TEntity , TId > :
38+ IResourceService < TResource , TId >
3339 where TResource : class , IIdentifiable < TId >
3440 where TEntity : class , IIdentifiable < TId >
3541 {
@@ -38,18 +44,49 @@ public class MappingResourceService<TResource, TEntity, TId>
3844 private readonly ILogger _logger ;
3945 private readonly IMapper _mapper ;
4046
41- public MappingResourceService (
47+ public DefaultResourceService (
48+ IJsonApiContext jsonApiContext ,
49+ IEntityRepository < TEntity , TId > entityRepository ,
50+ ILoggerFactory loggerFactory )
51+ {
52+ // no mapper provided, TResource & TEntity must be the same type
53+ if ( typeof ( TResource ) != typeof ( TEntity ) )
54+ {
55+ throw new InvalidOperationException ( "Resource and Entity types are NOT the same. " +
56+ "Please provide a mapper." ) ;
57+ }
58+
59+ _jsonApiContext = jsonApiContext ;
60+ _entities = entityRepository ;
61+ _logger = loggerFactory . CreateLogger < DefaultResourceService < TResource , TEntity , TId > > ( ) ;
62+ }
63+
64+ public DefaultResourceService (
4265 IJsonApiContext jsonApiContext ,
4366 IEntityRepository < TEntity , TId > entityRepository ,
4467 ILoggerFactory loggerFactory ,
4568 IMapper mapper )
4669 {
4770 _jsonApiContext = jsonApiContext ;
4871 _entities = entityRepository ;
49- _logger = loggerFactory . CreateLogger < MappingResourceService < TResource , TEntity , TId > > ( ) ;
72+ _logger = loggerFactory . CreateLogger < DefaultResourceService < TResource , TEntity , TId > > ( ) ;
5073 _mapper = mapper ;
5174 }
5275
76+ public virtual async Task < TResource > CreateAsync ( TResource resource )
77+ {
78+ var entity = ( typeof ( TResource ) == typeof ( TEntity ) ) ? resource as TEntity :
79+ _mapper . Map < TEntity > ( resource ) ;
80+ entity = await _entities . CreateAsync ( entity ) ;
81+ return ( typeof ( TResource ) == typeof ( TEntity ) ) ? entity as TResource :
82+ _mapper . Map < TResource > ( entity ) ;
83+ }
84+
85+ public virtual async Task < bool > DeleteAsync ( TId id )
86+ {
87+ return await _entities . DeleteAsync ( id ) ;
88+ }
89+
5390 public virtual async Task < IEnumerable < TResource > > GetAsync ( )
5491 {
5592 var entities = _entities . Get ( ) ;
@@ -75,25 +112,12 @@ public virtual async Task<TResource> GetAsync(TId id)
75112 else
76113 {
77114 TEntity entity = await _entities . GetAsync ( id ) ;
78- dto = _mapper . Map < TResource > ( entity ) ;
115+ dto = ( typeof ( TResource ) == typeof ( TEntity ) ) ? entity as TResource :
116+ _mapper . Map < TResource > ( entity ) ;
79117 }
80118 return dto ;
81119 }
82120
83- private bool ShouldIncludeRelationships ( )
84- => ( _jsonApiContext . QuerySet ? . IncludedRelationships != null && _jsonApiContext . QuerySet . IncludedRelationships . Count > 0 ) ;
85-
86- private async Task < TResource > GetWithRelationshipsAsync ( TId id )
87- {
88- var query = _entities . Get ( ) . Where ( e => e . Id . Equals ( id ) ) ;
89- _jsonApiContext . QuerySet . IncludedRelationships . ForEach ( r =>
90- {
91- query = _entities . Include ( query , r ) ;
92- } ) ;
93- var value = await _entities . FirstOrDefaultAsync ( query ) ;
94- return _mapper . Map < TResource > ( value ) ;
95- }
96-
97121 public virtual async Task < object > GetRelationshipsAsync ( TId id , string relationshipName )
98122 => await GetRelationshipAsync ( id , relationshipName ) ;
99123
@@ -107,26 +131,23 @@ public virtual async Task<object> GetRelationshipAsync(TId id, string relationsh
107131 throw new JsonApiException ( 404 , $ "Relationship { relationshipName } not found.") ;
108132 }
109133
110- var resource = _mapper . Map < TResource > ( entity ) ;
134+ var resource = ( typeof ( TResource ) == typeof ( TEntity ) ) ? entity as TResource :
135+ _mapper . Map < TResource > ( entity ) ;
111136 var relationship = _jsonApiContext . ContextGraph . GetRelationship ( resource , relationshipName ) ;
112137 return relationship ;
113138 }
114139
115- public virtual async Task < TResource > CreateAsync ( TResource resource )
116- {
117- var entity = _mapper . Map < TEntity > ( resource ) ;
118- entity = await _entities . CreateAsync ( entity ) ;
119- return _mapper . Map < TResource > ( entity ) ;
120- }
121-
122140 public virtual async Task < TResource > UpdateAsync ( TId id , TResource resource )
123141 {
124- var entity = _mapper . Map < TEntity > ( resource ) ;
142+ var entity = ( typeof ( TResource ) == typeof ( TEntity ) ) ? resource as TEntity :
143+ _mapper . Map < TEntity > ( resource ) ;
125144 entity = await _entities . UpdateAsync ( id , entity ) ;
126- return _mapper . Map < TResource > ( entity ) ;
145+ return ( typeof ( TResource ) == typeof ( TEntity ) ) ? entity as TResource :
146+ _mapper . Map < TResource > ( entity ) ;
127147 }
128148
129- public virtual async Task UpdateRelationshipsAsync ( TId id , string relationshipName , List < DocumentData > relationships )
149+ public virtual async Task UpdateRelationshipsAsync ( TId id , string relationshipName ,
150+ List < DocumentData > relationships )
130151 {
131152 var entity = await _entities . GetAndIncludeAsync ( id , relationshipName ) ;
132153 if ( entity == null )
@@ -137,16 +158,18 @@ public virtual async Task UpdateRelationshipsAsync(TId id, string relationshipNa
137158 var relationship = _jsonApiContext . ContextGraph
138159 . GetContextEntity ( typeof ( TResource ) )
139160 . Relationships
140- . FirstOrDefault ( r => r . PublicRelationshipName == relationshipName ) ;
161+ . FirstOrDefault ( r => r . Is ( relationshipName ) ) ;
141162 var relationshipType = relationship . Type ;
142163
143164 // update relationship type with internalname
144165 var entityProperty = typeof ( TEntity ) . GetProperty ( relationship . InternalRelationshipName ) ;
145166 if ( entityProperty == null )
146167 {
147- throw new JsonApiException ( 404 , $ "Property { relationship . InternalRelationshipName } could not be found on entity.") ;
168+ throw new JsonApiException ( 404 , $ "Property { relationship . InternalRelationshipName } " +
169+ $ "could not be found on entity.") ;
148170 }
149- relationship . Type = relationship . IsHasMany ? entityProperty . PropertyType . GetGenericArguments ( ) [ 0 ] : entityProperty . PropertyType ;
171+ relationship . Type = relationship . IsHasMany ? entityProperty . PropertyType . GetGenericArguments ( ) [ 0 ] :
172+ entityProperty . PropertyType ;
150173
151174 var relationshipIds = relationships . Select ( r => r ? . Id ? . ToString ( ) ) ;
152175
@@ -155,9 +178,26 @@ public virtual async Task UpdateRelationshipsAsync(TId id, string relationshipNa
155178 relationship . Type = relationshipType ;
156179 }
157180
158- public virtual async Task < bool > DeleteAsync ( TId id )
181+ protected virtual async Task < IEnumerable < TResource > > ApplyPageQueryAsync ( IQueryable < TEntity > entities )
159182 {
160- return await _entities . DeleteAsync ( id ) ;
183+ var pageManager = _jsonApiContext . PageManager ;
184+ if ( ! pageManager . IsPaginated )
185+ {
186+ var allEntities = await _entities . ToListAsync ( entities ) ;
187+ return ( typeof ( TResource ) == typeof ( TEntity ) ) ? allEntities as IEnumerable < TResource > :
188+ _mapper . Map < IEnumerable < TResource > > ( allEntities ) ;
189+ }
190+
191+ if ( _logger ? . IsEnabled ( LogLevel . Information ) == true )
192+ {
193+ _logger ? . LogInformation ( $ "Applying paging query. Fetching page { pageManager . CurrentPage } " +
194+ $ "with { pageManager . PageSize } entities") ;
195+ }
196+
197+ var pagedEntities = await _entities . PageAsync ( entities , pageManager . PageSize ,
198+ pageManager . CurrentPage ) ;
199+ return ( typeof ( TResource ) == typeof ( TEntity ) ) ? pagedEntities as IEnumerable < TResource > :
200+ _mapper . Map < IEnumerable < TResource > > ( pagedEntities ) ;
161201 }
162202
163203 protected virtual IQueryable < TEntity > ApplySortAndFilterQuery ( IQueryable < TEntity > entities )
@@ -177,21 +217,8 @@ protected virtual IQueryable<TEntity> ApplySortAndFilterQuery(IQueryable<TEntity
177217 return entities ;
178218 }
179219
180- protected virtual async Task < IEnumerable < TResource > > ApplyPageQueryAsync ( IQueryable < TEntity > entities )
181- {
182- var pageManager = _jsonApiContext . PageManager ;
183- if ( ! pageManager . IsPaginated )
184- return _mapper . Map < IEnumerable < TResource > > ( await _entities . ToListAsync ( entities ) ) ;
185-
186- if ( _logger ? . IsEnabled ( LogLevel . Information ) == true )
187- {
188- _logger ? . LogInformation ( $ "Applying paging query. Fetching page { pageManager . CurrentPage } with { pageManager . PageSize } entities") ;
189- }
190-
191- return _mapper . Map < IEnumerable < TResource > > ( await _entities . PageAsync ( entities , pageManager . PageSize , pageManager . CurrentPage ) ) ;
192- }
193-
194- protected virtual IQueryable < TEntity > IncludeRelationships ( IQueryable < TEntity > entities , List < string > relationships )
220+ protected virtual IQueryable < TEntity > IncludeRelationships ( IQueryable < TEntity > entities ,
221+ List < string > relationships )
195222 {
196223 _jsonApiContext . IncludedRelationships = relationships ;
197224
@@ -200,5 +227,21 @@ protected virtual IQueryable<TEntity> IncludeRelationships(IQueryable<TEntity> e
200227
201228 return entities ;
202229 }
230+
231+ private async Task < TResource > GetWithRelationshipsAsync ( TId id )
232+ {
233+ var query = _entities . Get ( ) . Where ( e => e . Id . Equals ( id ) ) ;
234+ _jsonApiContext . QuerySet . IncludedRelationships . ForEach ( r =>
235+ {
236+ query = _entities . Include ( query , r ) ;
237+ } ) ;
238+ var value = await _entities . FirstOrDefaultAsync ( query ) ;
239+ return ( typeof ( TResource ) == typeof ( TEntity ) ) ? value as TResource :
240+ _mapper . Map < TResource > ( value ) ;
241+ }
242+
243+ private bool ShouldIncludeRelationships ( )
244+ => ( _jsonApiContext . QuerySet ? . IncludedRelationships != null &&
245+ _jsonApiContext . QuerySet . IncludedRelationships . Count > 0 ) ;
203246 }
204247}
0 commit comments