PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Bowling/Bowling.Domain/Concrete/EntityFramework/IRepositoryExtensions.cs

https://github.com/edqwerty1/Bowling
C# | 290 lines | 85 code | 8 blank | 197 comment | 22 complexity | 608d86abd4da140212d458bfddf0bfda MD5 | raw file
  1. namespace Bowling.Domain.Abstract
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics.CodeAnalysis;
  6. using System.Diagnostics.Contracts;
  7. using System.Linq;
  8. using System.Linq.Expressions;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. /// <summary>
  12. /// Provides extension methods for the <see cref="IRepository{T}"/> and <see cref="IRepository{T}"/> interfaces.
  13. /// </summary>
  14. public static class IRepositoryExtensions
  15. {
  16. /// <summary>
  17. /// Retrieves all items in the repository satisfied by the specified query asynchronously.
  18. /// </summary>
  19. /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
  20. /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
  21. /// <param name="queryShaper">The <see cref="Func{T,TResult}">function</see> that shapes the <see cref="IQueryable{T}">query</see> to execute.</param>
  22. /// <returns>A <see cref="Task{T}">task</see> containing the retrieved <see cref="IEnumerable{T}">sequence</see>
  23. /// of <typeparamref name="T">items</typeparamref>.</returns>
  24. /// <example>The following example demonstrates how to paginate the items in a repository using an example query.
  25. /// <code><![CDATA[
  26. /// using Microsoft.DesignPatterns.Examples;
  27. /// using System;
  28. /// using System.Collections.Generic;
  29. /// using System.Linq;
  30. /// using System.Threading;
  31. /// using System.Threading.Tasks;
  32. ///
  33. /// public async static void Main()
  34. /// {
  35. /// var index = 0;
  36. /// var repository = new MyRepository();
  37. ///
  38. /// foreach ( var item in await repository.GetAsync( q => q.Where( i => i.FirstName.StartsWith( "Jo" ) ).OrderBy( i => i.LastName ) );
  39. /// Console.WriteLine( i => i.ToString() );
  40. /// }
  41. /// ]]>
  42. /// </code></example>
  43. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
  44. [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
  45. public static Task<IEnumerable<T>> GetAsync<T>(this IRepository<T> repository, Func<IQueryable<T>, IQueryable<T>> queryShaper) where T : class
  46. {
  47. Contract.Requires(repository != null);
  48. Contract.Requires(queryShaper != null);
  49. Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
  50. return repository.GetAsync(queryShaper, CancellationToken.None);
  51. }
  52. /// <summary>
  53. /// Retrieves a query result asynchronously.
  54. /// </summary>
  55. /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
  56. /// <typeparam name="TResult">The <see cref="Type">type</see> of result to retrieve.</typeparam>
  57. /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
  58. /// <param name="queryShaper">The <see cref="Func{T,TResult}">function</see> that shapes the <see cref="IQueryable{T}">query</see> to execute.</param>
  59. /// <returns>A <see cref="Task{T}">task</see> containing the <typeparamref name="TResult">result</typeparamref> of the operation.</returns>
  60. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
  61. [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
  62. public static Task<TResult> GetAsync<T, TResult>(this IRepository<T> repository, Func<IQueryable<T>, TResult> queryShaper) where T : class
  63. {
  64. Contract.Requires(repository != null);
  65. Contract.Requires(queryShaper != null);
  66. Contract.Ensures(Contract.Result<Task<TResult>>() != null);
  67. return repository.GetAsync(queryShaper, CancellationToken.None);
  68. }
  69. /// <summary>
  70. /// Retrieves all items in the repository asynchronously.
  71. /// </summary>
  72. /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
  73. /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
  74. /// <returns>A <see cref="Task{T}">task</see> containing the <see cref="IEnumerable{T}">sequence</see>
  75. /// of all <typeparamref name="T">items</typeparamref> in the repository.</returns>
  76. /// <example>The following example demonstrates how to retrieve all items in a repository.
  77. /// <code><![CDATA[
  78. /// using Microsoft.DesignPatterns.Examples;
  79. /// using System;
  80. /// using System.Collections.Generic;
  81. /// using System.Linq;
  82. /// using System.Threading;
  83. /// using System.Threading.Tasks;
  84. ///
  85. /// public async static void Main()
  86. /// {
  87. /// var repository = new MyRepository();
  88. ///
  89. /// foreach ( var item in await repository.GetAllAsync( i => i.LastName == "Doe" ) )
  90. /// Console.WriteLine( item.ToString() );
  91. /// }
  92. /// ]]>
  93. /// </code></example>
  94. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
  95. [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
  96. public static Task<IEnumerable<T>> GetAllAsync<T>(this IRepository<T> repository) where T : class
  97. {
  98. Contract.Requires(repository != null);
  99. Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
  100. return repository.GetAsync(q => q, CancellationToken.None);
  101. }
  102. /// <summary>
  103. /// Retrieves all items in the repository asynchronously.
  104. /// </summary>
  105. /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
  106. /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
  107. /// <param name="cancellationToken">The <see cref="CancellationToken">cancellation token</see> that can be used to cancel the operation.</param>
  108. /// <returns>A <see cref="Task{T}">task</see> containing the <see cref="IEnumerable{T}">sequence</see>
  109. /// of all <typeparamref name="T">items</typeparamref> in the repository.</returns>
  110. /// <example>The following example demonstrates how to retrieve all items in a repository.
  111. /// <code><![CDATA[
  112. /// using Microsoft.DesignPatterns.Examples;
  113. /// using System;
  114. /// using System.Collections.Generic;
  115. /// using System.Linq;
  116. /// using System.Threading;
  117. /// using System.Threading.Tasks;
  118. ///
  119. /// public async static void Main()
  120. /// {
  121. /// var repository = new MyRepository();
  122. /// var cancellationToken = new CancellationToken();
  123. ///
  124. /// foreach ( var item in await repository.GetAllAsync( i => i.LastName == "Doe", cancellationToken ) )
  125. /// Console.WriteLine( item.ToString() );
  126. /// }
  127. /// ]]>
  128. /// </code></example>
  129. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
  130. [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
  131. public static Task<IEnumerable<T>> GetAllAsync<T>(this IRepository<T> repository, CancellationToken cancellationToken) where T : class
  132. {
  133. Contract.Requires(repository != null);
  134. Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
  135. return repository.GetAsync(q => q, cancellationToken);
  136. }
  137. /// <summary>
  138. /// Searches for items in the repository that match the specified predicate asynchronously.
  139. /// </summary>
  140. /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
  141. /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
  142. /// <param name="predicate">The <see cref="Expression{T}">expression</see> representing the predicate used to
  143. /// match the requested <typeparamref name="T">items</typeparamref>.</param>
  144. /// <returns>A <see cref="Task{T}">task</see> containing the matched <see cref="IEnumerable{T}">sequence</see>
  145. /// of <typeparamref name="T">items</typeparamref>.</returns>
  146. /// <example>The following example demonstrates how to find items in a repository.
  147. /// <code><![CDATA[
  148. /// using Microsoft.DesignPatterns.Examples;
  149. /// using System;
  150. /// using System.Collections.Generic;
  151. /// using System.Linq;
  152. /// using System.Threading;
  153. /// using System.Threading.Tasks;
  154. ///
  155. /// public async static void Main()
  156. /// {
  157. /// var repository = new MyRepository();
  158. /// var items = await repository.FindByAsync( i => i.LastName == "Doe" );
  159. /// items.ForEach( i => Console.WriteLine( i.ToString() ) );
  160. /// }
  161. /// ]]>
  162. /// </code></example>
  163. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
  164. [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
  165. public static Task<IEnumerable<T>> FindByAsync<T>(this IRepository<T> repository, Expression<Func<T, bool>> predicate) where T : class
  166. {
  167. Contract.Requires(repository != null);
  168. Contract.Requires(predicate != null);
  169. Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
  170. return repository.GetAsync(q => q.Where(predicate), CancellationToken.None);
  171. }
  172. /// <summary>
  173. /// Searches for items in the repository that match the specified predicate asynchronously.
  174. /// </summary>
  175. /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
  176. /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
  177. /// <param name="predicate">The <see cref="Expression{T}">expression</see> representing the predicate used to
  178. /// match the requested <typeparamref name="T">items</typeparamref>.</param>
  179. /// <param name="cancellationToken">The <see cref="CancellationToken">cancellation token</see> that can be used to cancel the operation.</param>
  180. /// <returns>A <see cref="Task{T}">task</see> containing the matched <see cref="IEnumerable{T}">sequence</see>
  181. /// of <typeparamref name="T">items</typeparamref>.</returns>
  182. /// <example>The following example demonstrates how to find items in a repository.
  183. /// <code><![CDATA[
  184. /// using Microsoft.DesignPatterns.Examples;
  185. /// using System;
  186. /// using System.Collections.Generic;
  187. /// using System.Linq;
  188. /// using System.Threading;
  189. /// using System.Threading.Tasks;
  190. ///
  191. /// public async static void Main()
  192. /// {
  193. /// var repository = new MyRepository();
  194. /// var cancellationToken = new CancellationToken();
  195. /// var items = await repository.FindByAsync( i => i.LastName == "Doe", cancellationToken );
  196. /// items.ForEach( i => Console.WriteLine( i.ToString() ) );
  197. /// }
  198. /// ]]>
  199. /// </code></example>
  200. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
  201. [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
  202. public static Task<IEnumerable<T>> FindByAsync<T>(this IRepository<T> repository, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken) where T : class
  203. {
  204. Contract.Requires(repository != null);
  205. Contract.Requires(predicate != null);
  206. Contract.Ensures(Contract.Result<Task<IEnumerable<T>>>() != null);
  207. return repository.GetAsync(q => q.Where(predicate), cancellationToken);
  208. }
  209. /// <summary>
  210. /// Retrieves a single item in the repository matching the specified predicate asynchronously.
  211. /// </summary>
  212. /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
  213. /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
  214. /// <param name="predicate">The <see cref="Expression{T}">expression</see> representing the predicate used to
  215. /// match the requested <typeparamref name="T">item</typeparamref>.</param>
  216. /// <returns>A <see cref="Task{T}">task</see> containing the matched <typeparamref name="T">item</typeparamref>
  217. /// or null if no match was found.</returns>
  218. /// <example>The following example demonstrates how to retrieve a single item from a repository.
  219. /// <code><![CDATA[
  220. /// using Microsoft.DesignPatterns.Examples;
  221. /// using System;
  222. /// using System.Collections.Generic;
  223. /// using System.Linq;
  224. /// using System.Threading;
  225. /// using System.Threading.Tasks;
  226. ///
  227. /// public async static void Main()
  228. /// {
  229. /// var repository = new MyRepository();
  230. /// var item = await repository.GetSingleAsync( i => i.Id == 1 );
  231. /// Console.WriteLine( item.ToString() );
  232. /// }
  233. /// ]]>
  234. /// </code></example>
  235. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
  236. [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
  237. public static Task<T> GetSingleAsync<T>(this IRepository<T> repository, Expression<Func<T, bool>> predicate) where T : class
  238. {
  239. Contract.Requires(repository != null);
  240. Contract.Requires(predicate != null);
  241. Contract.Ensures(Contract.Result<Task<T>>() != null);
  242. return repository.GetSingleAsync(predicate, CancellationToken.None);
  243. }
  244. /// <summary>
  245. /// Retrieves a single item in the repository matching the specified predicate asynchronously.
  246. /// </summary>
  247. /// <typeparam name="T">The <see cref="Type">type</see> of item in the repository.</typeparam>
  248. /// <param name="repository">The extended <see cref="IRepository{T}">repository</see>.</param>
  249. /// <param name="predicate">The <see cref="Expression{T}">expression</see> representing the predicate used to
  250. /// match the requested <typeparamref name="T">item</typeparamref>.</param>
  251. /// <param name="cancellationToken">The <see cref="CancellationToken">cancellation token</see> that can be used to cancel the operation.</param>
  252. /// <returns>A <see cref="Task{T}">task</see> containing the matched <typeparamref name="T">item</typeparamref>
  253. /// or null if no match was found.</returns>
  254. /// <example>The following example demonstrates how to retrieve a single item from a repository.
  255. /// <code><![CDATA[
  256. /// using Microsoft.DesignPatterns.Examples;
  257. /// using System;
  258. /// using System.Collections.Generic;
  259. /// using System.Linq;
  260. /// using System.Threading;
  261. /// using System.Threading.Tasks;
  262. ///
  263. /// public async static void Main()
  264. /// {
  265. /// var repository = new MyRepository();
  266. /// var item = await repository.GetSingleAsync( i => i.Id == 1 );
  267. /// Console.WriteLine( item.ToString() );
  268. /// }
  269. /// ]]>
  270. /// </code></example>
  271. [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Required for generics support.")]
  272. [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract.")]
  273. public static async Task<T> GetSingleAsync<T>(this IRepository<T> repository, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken) where T : class
  274. {
  275. Contract.Requires(repository != null);
  276. Contract.Requires(predicate != null);
  277. Contract.Ensures(Contract.Result<Task<T>>() != null);
  278. var items = await repository.GetAsync(q => q.Where(predicate), cancellationToken);
  279. return items.SingleOrDefault();
  280. }
  281. }
  282. }