1+ ## OData
12AutoMapper extentions for mapping expressions (OData)
23
34To use, configure using the configuration helper method:
@@ -7,4 +8,78 @@ Mapper.Initialize(cfg => {
78 cfg .AddExpressionMapping ();
89 // Rest of your configuration
910 });
10- ```
11+ ```
12+
13+ ## DTO Queries
14+ Expression Mapping also supports writing queries against the mapped objects. Take the following source and destination types:
15+ ``` csharp
16+ public class User
17+ {
18+ public int Id { get ; set ; }
19+ public string Name { get ; set ; }
20+ }
21+
22+ public class Request
23+ {
24+ public int Id { get ; set ; }
25+ public int AssigneeId { get ; set ; }
26+ public User Assignee { get ; set ; }
27+ }
28+
29+ public class UserDTO
30+ {
31+ public int Id { get ; set ; }
32+ public string Name { get ; set ; }
33+ }
34+
35+ public class RequestDTO
36+ {
37+ public int Id { get ; set ; }
38+ public UserDTO Assignee { get ; set ; }
39+ }
40+ ```
41+
42+ We can write LINQ expressions against the DTO collections.
43+ ``` csharp
44+ ICollection < RequestDTO > requests = await context .Request .GetItemsAsync (mapper , r => r .Id > 0 && r .Id < 3 , null , new List <Expression <Func <IQueryable <RequestDTO >, IIncludableQueryable <RequestDTO , object >>>>() { item => item .Include (s => s .Assignee ) });
45+ ICollection < UserDTO > users = await context .User .GetItemsAsync <UserDTO , User >(mapper , u => u .Id > 0 && u .Id < 4 , q => q .OrderBy (u => u .Name ));
46+ int count = await context .Request .Query <RequestDTO , Request , int , int >(mapper , q => q .Count (r => r .Id > 1 ));
47+ ```
48+ The methods below map the DTO query expresions to the equivalent data query expressions. The call to IMapper.Map converts the data query results back to the DTO (or model) object types.
49+ ``` csharp
50+ static class Extensions
51+ {
52+ internal static async Task <TModelResult > Query <TModel , TData , TModelResult , TDataResult >(this IQueryable <TData > query , IMapper mapper ,
53+ Expression <Func <IQueryable <TModel >, TModelResult >> queryFunc ) where TData : class
54+ {
55+ // Map the expressions
56+ Func < IQueryable < TData > , TDataResult > mappedQueryFunc = mapper .MapExpression <Expression <Func <IQueryable <TData >, TDataResult >>>(queryFunc ).Compile ();
57+
58+ // execute the query
59+ return mapper .Map <TDataResult , TModelResult >(mappedQueryFunc (query ));
60+ }
61+
62+ internal static async Task <ICollection <TModel >> GetItemsAsync <TModel , TData >(this IQueryable <TData > query , IMapper mapper ,
63+ Expression <Func <TModel , bool >> filter = null ,
64+ Expression <Func <IQueryable <TModel >, IQueryable <TModel >>> queryFunc = null ,
65+ ICollection <Expression <Func <IQueryable <TModel >, IIncludableQueryable <TModel , object >>>> includeProperties = null )
66+ {
67+ // Map the expressions
68+ Expression < Func < TData , bool >> f = mapper .MapExpression <Expression <Func <TData , bool >>>(filter );
69+ Func < IQueryable < TData > , IQueryable < TData >> mappedQueryFunc = mapper .MapExpression <Expression <Func <IQueryable <TData >, IQueryable <TData >>>>(queryFunc )? .Compile ();
70+ ICollection < Expression < Func < IQueryable < TData > , IIncludableQueryable < TData , object >>> > includes = mapper .MapIncludesList <Expression <Func <IQueryable <TData >, IIncludableQueryable <TData , object >>>>(includeProperties );
71+
72+ if (f != null )
73+ query = query .Where (f );
74+
75+ if (includes != null )
76+ query = includes .Select (i => i .Compile ()).Aggregate (query , (list , next ) => query = next (query ));
77+
78+ // Call the store
79+ ICollection < TData > result = mappedQueryFunc != null ? await mappedQueryFunc (query ).ToListAsync () : await query .ToListAsync ();
80+
81+ // Map and return the data
82+ return mapper .Map <IEnumerable <TData >, IEnumerable <TModel >>(result ).ToList ();
83+ }
84+ }
85+ ```
0 commit comments