EasyDatabaseFacadeExtensions.cs 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Common;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using Microsoft.EntityFrameworkCore;
  9. using Microsoft.EntityFrameworkCore.Infrastructure;
  10. using Microsoft.EntityFrameworkCore.Internal;
  11. using Microsoft.EntityFrameworkCore.Storage;
  12. using Microsoft.Extensions.DependencyInjection;
  13. using EasyDevCore.Common;
  14. using System.Data;
  15. using System.Runtime.CompilerServices;
  16. using System.Dynamic;
  17. using System.Collections;
  18. using System.Reflection;
  19. using System.Collections.Concurrent;
  20. using EasyDev.Database;
  21. namespace EasyDevCore.Database.EntityFrameworkCore
  22. {
  23. /// <summary>
  24. ///
  25. /// </summary>
  26. /// <typeparam name="TModel">The type of the model.</typeparam>
  27. /// <typeparam name="TResult">The type of the result.</typeparam>
  28. /// <param name="models">The models.</param>
  29. /// <param name="hasNextResult">if set to <c>true</c> [has next result].</param>
  30. /// <returns></returns>
  31. public delegate TResult FuncResultList<TModel, TResult>(out IList<TModel> models, out bool hasNextResult);
  32. /// <summary>
  33. ///
  34. /// </summary>
  35. /// <typeparam name="TModel">The type of the model.</typeparam>
  36. /// <typeparam name="TResult">The type of the result.</typeparam>
  37. /// <param name="models">The models.</param>
  38. /// <returns></returns>
  39. public delegate TResult StoreResultList<TModel, TResult>(out IList<TModel> models);
  40. /// <summary>
  41. ///
  42. /// </summary>
  43. /// <typeparam name="TModel">The type of the model.</typeparam>
  44. /// <typeparam name="TResult">The type of the result.</typeparam>
  45. /// <param name="models">The models.</param>
  46. /// <returns></returns>
  47. public delegate TResult StoreResultModel<TModel, TResult>(out TModel models);
  48. /// <summary>
  49. ///
  50. /// </summary>
  51. /// <typeparam name="TModel">The type of the model.</typeparam>
  52. /// <typeparam name="TOut">The type of the out.</typeparam>
  53. /// <typeparam name="TResult">The type of the result.</typeparam>
  54. /// <param name="models">The models.</param>
  55. /// <param name="outVars">The out vars.</param>
  56. /// <param name="hasNextResult">if set to <c>true</c> [has next result].</param>
  57. /// <returns></returns>
  58. public delegate TResult StoreResultList<TModel, TOut, TResult>(out IList<TModel> models, out TOut outVars, out bool hasNextResult);
  59. /// <summary>
  60. ///
  61. /// </summary>
  62. public static class EasyDatabaseFacadeExtensions
  63. {
  64. private static ConcurrentDictionary<string, Type> _ParameterTypesCache = new();
  65. private static string GetExecStoreProcedureString(string storeProcedure, IEnumerable<EasyDbParameter> parameters)
  66. {
  67. return
  68. @"--" + string.Join(",", parameters.OfType<EasyDbParameter>().Where(p => p.ParameterName.In("ApplicationID", "UserID", "HostName", "ScreenID")).Select(p => $@"{p.ParameterName}={p.Value}")) +
  69. @"
  70. EXEC @RETURN_VALUE = " + storeProcedure + " " + string.Join(",", parameters.OfType<EasyDbParameter>().Where(p => !p.ParameterName.In("RETURN_VALUE", "RETURN_ROWS_EFFECTED")).Select(p => $"@{p.ParameterName} = @{p.ParameterName}"
  71. + (p.Direction.In(ParameterDirection.Output, ParameterDirection.InputOutput) ? " OUTPUT" : "")));
  72. }
  73. /// <summary>
  74. /// Synchronizes the output parameters.
  75. /// </summary>
  76. /// <param name="inParams">The in parameters.</param>
  77. /// <param name="outParams">The out parameters.</param>
  78. private static void SyncOutputParameters(object inParams, IEnumerable<EasyDbParameter> outParams)
  79. {
  80. IEnumerable<EasyDbParameter> fixInParams = null;
  81. if (inParams == outParams) return;
  82. if (inParams is object[] && ((object[])inParams).Length == 1 && ((object[])inParams)[0] is EasyDbParameterCollection)
  83. {
  84. fixInParams = (EasyDbParameterCollection)((object[])inParams)[0];
  85. }
  86. if (inParams is IEnumerable<EasyDbParameter>)
  87. {
  88. fixInParams = (IEnumerable<EasyDbParameter>)inParams;
  89. }
  90. if (fixInParams == null) return;
  91. var synchList = from pIn in fixInParams
  92. join pOut in outParams on pIn.ParameterName equals pOut.ParameterName
  93. where pIn.Direction.In(ParameterDirection.Output, ParameterDirection.InputOutput, ParameterDirection.ReturnValue)
  94. select new { pIn, pOut.Value };
  95. synchList.ForEach(v => v.pIn.Value = v.Value);
  96. }
  97. /// <summary>
  98. /// Creates the parameter.
  99. /// </summary>
  100. /// <param name="database">The database.</param>
  101. /// <param name="parameter">The parameter.</param>
  102. /// <returns></returns>
  103. public static EasyDbParameter CreateParameter(this DatabaseFacade database, EasyDbParameter parameter)
  104. {
  105. if (!_ParameterTypesCache.TryGetValue(database.ProviderName, out Type type))
  106. {
  107. var command = database.GetDbConnection().CreateCommand();
  108. type = command.CreateParameter().GetType();
  109. _ParameterTypesCache.TryAdd(database.ProviderName, type);
  110. }
  111. EasyDbParameter param = (EasyDbParameter)type.CreateInstance(parameter.ParameterName, parameter.Value ?? DBNull.Value);
  112. param.Direction = parameter.Direction;
  113. param.Scale = parameter.Scale != 0 ? parameter.Scale : param.Scale;
  114. param.Precision = parameter.Precision != 0 ? parameter.Precision : param.Precision;
  115. param.Size = parameter.Precision != 0 ? parameter.Precision : param.Precision;
  116. if (param.Value is DateTime && ((DateTime)param.Value).Date <= DateTime.Parse("1900/01/01"))
  117. {
  118. param.Value = DateTime.Parse("1900/01/01");
  119. }
  120. if (param.Direction == ParameterDirection.InputOutput && param.Value.GetType() == typeof(decimal))
  121. {
  122. param.Precision = 28;
  123. param.Scale = 8;
  124. }
  125. if (param.DbType.In(DbType.String, DbType.AnsiString, DbType.StringFixedLength, DbType.AnsiStringFixedLength) && param.Direction.In(ParameterDirection.InputOutput, ParameterDirection.Output))
  126. {
  127. param.Size = -1;
  128. }
  129. return param;
  130. }
  131. /// <summary>
  132. /// Converts the parameters.
  133. /// </summary>
  134. /// <param name="database">The database.The database.</param>
  135. /// <param name="parameters">The parameters.The parameters.</param>
  136. /// <returns>
  137. /// <br />
  138. /// </returns>
  139. private static IEnumerable<EasyDbParameter> ConvertParameters(DatabaseFacade database, EasyDbParameterCollection parameters)
  140. {
  141. IEnumerable<EasyDbParameter> result = null;
  142. if (parameters != null && parameters.Any() && !(parameters.First() is EasyDbParameter))
  143. {
  144. result = parameters;
  145. foreach (var p in parameters.Where(dp => !dp.Direction.In(ParameterDirection.InputOutput, ParameterDirection.Output) && (dp.Value == null || dp.Value == DBNull.Value)).ToArray())
  146. {
  147. parameters.Remove(p.ParameterName);
  148. }
  149. }
  150. else
  151. {
  152. result = new EasyDbParameterCollection();
  153. if (parameters != null)
  154. {
  155. foreach (EasyDbParameter param in parameters)
  156. {
  157. if (param.Direction.In(ParameterDirection.InputOutput, ParameterDirection.Output) || param.Value != DBNull.Value && param.Value != null)
  158. {
  159. ((EasyDbParameterCollection)result).Add(database.CreateParameter(param));
  160. }
  161. }
  162. }
  163. }
  164. return result;
  165. }
  166. /// <summary>
  167. /// Gets the context.
  168. /// </summary>
  169. /// <param name="database">The database.</param>
  170. /// <returns></returns>
  171. public static DbContext GetContext(this DatabaseFacade database)
  172. {
  173. object internalSet = database
  174. .GetType()
  175. .GetField("_internalSet", BindingFlags.NonPublic | BindingFlags.Instance)
  176. .GetValue(database);
  177. object internalContext = internalSet
  178. .GetType()
  179. .BaseType
  180. .GetField("_internalContext", BindingFlags.NonPublic | BindingFlags.Instance)
  181. .GetValue(internalSet);
  182. return (DbContext)internalContext
  183. .GetType()
  184. .GetProperty("Owner", BindingFlags.Instance | BindingFlags.Public)
  185. .GetValue(internalContext, null);
  186. }
  187. /// <summary>
  188. /// Executes the non query asynchronous.
  189. /// </summary>
  190. /// <param name="database">The database.</param>
  191. /// <param name="cancellationToken">The cancellation token.</param>
  192. /// <param name="sql">The SQL.</param>
  193. /// <param name="parameters">The parameters.</param>
  194. /// <returns></returns>
  195. public static Task<int> ExecuteNonQueryAsync(this DatabaseFacade database,
  196. CancellationToken cancellationToken,
  197. string sql,
  198. params object[] parameters)
  199. {
  200. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  201. var concurrencyDetector = database.GetService<IConcurrencyDetector>();
  202. using (concurrencyDetector.EnterCriticalSection())
  203. {
  204. var rawSqlCommand = database.GetService<IRawSqlCommandBuilder>().Build(sql, fixParams);
  205. var paramObject = new RelationalCommandParameterObject(database.GetService<IRelationalConnection>(), rawSqlCommand.ParameterValues, null, null, null);
  206. return rawSqlCommand.RelationalCommand.ExecuteNonQueryAsync(paramObject, cancellationToken).ContinueWith(t =>
  207. {
  208. SyncOutputParameters(parameters, fixParams);
  209. return t.Result;
  210. });
  211. }
  212. }
  213. /// <summary>
  214. /// Executes the non query asynchronous.
  215. /// </summary>
  216. /// <param name="database">The database.</param>
  217. /// <param name="sql">The SQL.</param>
  218. /// <param name="parameters">The parameters.</param>
  219. /// <returns></returns>
  220. public static Task<int> ExecuteNonQueryAsync(this DatabaseFacade database,
  221. string sql,
  222. params object[] parameters)
  223. {
  224. return database.ExecuteNonQueryAsync(CancellationToken.None, sql, parameters);
  225. }
  226. /// <summary>
  227. /// Executes the non query.
  228. /// </summary>
  229. /// <param name="database">The database.</param>
  230. /// <param name="sql">The SQL.</param>
  231. /// <param name="parameters">The parameters.</param>
  232. /// <returns></returns>
  233. public static int ExecuteNonQuery(this DatabaseFacade database, string sql, params object[] parameters)
  234. {
  235. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  236. var concurrencyDetector = database.GetService<IConcurrencyDetector>();
  237. using (concurrencyDetector.EnterCriticalSection())
  238. {
  239. var rawSqlCommand = database.GetService<IRawSqlCommandBuilder>().Build(sql, fixParams);
  240. var paramObject = new RelationalCommandParameterObject(database.GetService<IRelationalConnection>(), rawSqlCommand.ParameterValues, null, null, null);
  241. var result = rawSqlCommand.RelationalCommand.ExecuteNonQuery(paramObject);
  242. SyncOutputParameters(parameters, fixParams);
  243. return result;
  244. }
  245. }
  246. /// <summary>
  247. /// Executes the scalar.
  248. /// </summary>
  249. /// <param name="database">The database.</param>
  250. /// <param name="sql">The SQL.</param>
  251. /// <param name="parameters">The parameters.</param>
  252. /// <returns></returns>
  253. public static object ExecuteScalar(this DatabaseFacade database, string sql, params object[] parameters)
  254. {
  255. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  256. var concurrencyDetector = database.GetService<IConcurrencyDetector>();
  257. using (concurrencyDetector.EnterCriticalSection())
  258. {
  259. var rawSqlCommand = database.GetService<IRawSqlCommandBuilder>().Build(sql, fixParams);
  260. var paramObject = new RelationalCommandParameterObject(database.GetService<IRelationalConnection>(), rawSqlCommand.ParameterValues, null, null, null);
  261. var result = rawSqlCommand.RelationalCommand.ExecuteScalar(paramObject);
  262. SyncOutputParameters(parameters, fixParams);
  263. return result;
  264. }
  265. }
  266. /// <summary>
  267. /// Executes the scalar asynchronous.
  268. /// </summary>
  269. /// <param name="database">The database.</param>
  270. /// <param name="sql">The SQL.</param>
  271. /// <param name="parameters">The parameters.</param>
  272. /// <returns></returns>
  273. public static Task<object> ExecuteScalarAsync(this DatabaseFacade database, string sql, params object[] parameters)
  274. {
  275. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  276. var concurrencyDetector = database.GetService<IConcurrencyDetector>();
  277. using (concurrencyDetector.EnterCriticalSection())
  278. {
  279. var rawSqlCommand = database.GetService<IRawSqlCommandBuilder>().Build(sql, fixParams);
  280. var paramObject = new RelationalCommandParameterObject(database.GetService<IRelationalConnection>(), rawSqlCommand.ParameterValues, null, null, null);
  281. var result = rawSqlCommand.RelationalCommand.ExecuteScalarAsync(paramObject);
  282. SyncOutputParameters(parameters, fixParams);
  283. return result;
  284. }
  285. }
  286. /// <summary>
  287. /// Executes the reader.
  288. /// </summary>
  289. /// <param name="database">The database facade.</param>
  290. /// <param name="sql">The SQL.</param>
  291. /// <param name="parameters">The parameters.</param>
  292. /// <returns></returns>
  293. public static RelationalDataReader ExecuteReader(this DatabaseFacade database, string sql, params object[] parameters)
  294. {
  295. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  296. var concurrencyDetector = database.GetService<IConcurrencyDetector>();
  297. using (concurrencyDetector.EnterCriticalSection())
  298. {
  299. var rawSqlCommand = database.GetService<IRawSqlCommandBuilder>().Build(sql, fixParams);
  300. var paramObject = new RelationalCommandParameterObject(database.GetService<IRelationalConnection>(), rawSqlCommand.ParameterValues, null, null, null);
  301. var result = rawSqlCommand.RelationalCommand.ExecuteReader(paramObject);
  302. SyncOutputParameters(parameters, fixParams);
  303. return result;
  304. }
  305. }
  306. /// <summary>
  307. /// Executes the reader asynchronous.
  308. /// </summary>
  309. /// <param name="database">The database facade.</param>
  310. /// <param name="cancellationToken">The cancellation token.</param>
  311. /// <param name="sql">The SQL.</param>
  312. /// <param name="parameters">The parameters.</param>
  313. /// <returns></returns>
  314. public static Task<RelationalDataReader> ExecuteReaderAsync(this DatabaseFacade database,
  315. CancellationToken cancellationToken,
  316. string sql,
  317. params object[] parameters)
  318. {
  319. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  320. var concurrencyDetector = database.GetService<IConcurrencyDetector>();
  321. using (concurrencyDetector.EnterCriticalSection())
  322. {
  323. var rawSqlCommand = database.GetService<IRawSqlCommandBuilder>().Build(sql, fixParams);
  324. var paramObject = new RelationalCommandParameterObject(database.GetService<IRelationalConnection>(), rawSqlCommand.ParameterValues, null, null, null);
  325. return rawSqlCommand.RelationalCommand.ExecuteReaderAsync(paramObject, cancellationToken).ContinueWith(t =>
  326. {
  327. SyncOutputParameters(parameters, fixParams);
  328. return t.Result;
  329. });
  330. }
  331. }
  332. /// <summary>
  333. /// Executes the reader asynchronous.
  334. /// </summary>
  335. /// <param name="database">The database.</param>
  336. /// <param name="sql">The SQL.</param>
  337. /// <param name="parameters">The parameters.</param>
  338. /// <returns></returns>
  339. public static Task<RelationalDataReader> ExecuteReaderAsync(this DatabaseFacade database,
  340. string sql,
  341. params object[] parameters)
  342. {
  343. return database.ExecuteReaderAsync(CancellationToken.None, sql, parameters);
  344. }
  345. /// <summary>
  346. /// Fetches the result.
  347. /// </summary>
  348. /// <typeparam name="T"></typeparam>
  349. /// <param name="reader">The reader.</param>
  350. /// <returns></returns>
  351. public static FuncResultList<T, RelationalDataReader> FetchResult<T>(this RelationalDataReader reader) where T : class, new()
  352. {
  353. List<T> list = new();
  354. var mapper = new DbDataReaderMapper<T>(reader);
  355. mapper.Map(row => list.Add(row));
  356. var nextResult = reader.DbDataReader.NextResult();
  357. if (!nextResult) reader.DbDataReader.Close();
  358. return (out IList<T> models, out bool hasNextResult) =>
  359. {
  360. models = list;
  361. hasNextResult = nextResult;
  362. return reader;
  363. };
  364. }
  365. /// <summary>
  366. /// Fetches the result json.
  367. /// </summary>
  368. /// <param name="reader">The reader.</param>
  369. /// <returns></returns>
  370. public static StoreResultModel<string, RelationalDataReader> FetchResultJson(this RelationalDataReader reader)
  371. {
  372. var json = reader.DbDataReader.FetchToJson();
  373. var nextResult = reader.DbDataReader.NextResult();
  374. if (!nextResult) reader.DbDataReader.Close();
  375. return (out string models) =>
  376. {
  377. models = json;
  378. return reader;
  379. };
  380. }
  381. /// <summary>
  382. /// Fetches the result dynamic.
  383. /// </summary>
  384. /// <param name="reader">The reader.</param>
  385. /// <returns></returns>
  386. /// <remarks></remarks>
  387. public static FuncResultList<dynamic, RelationalDataReader> FetchResultDynamic(this RelationalDataReader reader)
  388. {
  389. var list = reader.DbDataReader.FetchToDynamic();
  390. var nextResult = reader.DbDataReader.NextResult();
  391. if (!nextResult) reader.DbDataReader.Close();
  392. return (out IList<dynamic> models, out bool hasNextResult) =>
  393. {
  394. models = list;
  395. hasNextResult = nextResult;
  396. return reader;
  397. };
  398. }
  399. /// <summary>
  400. /// Fetches the result asynchronous.
  401. /// </summary>
  402. /// <typeparam name="T"></typeparam>
  403. /// <param name="reader">The reader.</param>
  404. /// <param name="cancellationToken">The cancellation token.</param>
  405. /// <returns></returns>
  406. public static async Task<FuncResultList<T, RelationalDataReader>> FetchResultAsync<T>(this RelationalDataReader reader,
  407. CancellationToken cancellationToken) where T : class, new()
  408. {
  409. List<T> list = new();
  410. var mapper = new DbDataReaderMapper<T>(reader);
  411. await mapper.MapAsync(row => list.Add(row), cancellationToken).ConfigureAwait(false);
  412. bool nextResult = await reader.DbDataReader.NextResultAsync(cancellationToken).ConfigureAwait(false);
  413. if (!nextResult) await reader.DbDataReader.CloseAsync();
  414. return (out IList<T> models, out bool hasNextResult) =>
  415. {
  416. models = list;
  417. hasNextResult = nextResult;
  418. return reader;
  419. };
  420. }
  421. /// <summary>
  422. /// Fetches the result asynchronous.
  423. /// </summary>
  424. /// <typeparam name="T"></typeparam>
  425. /// <param name="reader">The reader.</param>
  426. /// <returns></returns>
  427. public static async Task<FuncResultList<T, RelationalDataReader>> FetchResultAsync<T>(this RelationalDataReader reader) where T : class, new()
  428. {
  429. return await reader.FetchResultAsync<T>(CancellationToken.None).ConfigureAwait(false);
  430. }
  431. /// <summary>
  432. /// Fetches the result.
  433. /// </summary>
  434. /// <typeparam name="TResult">The type of the result.</typeparam>
  435. /// <param name="reader">The reader.</param>
  436. /// <param name="selector">The selector.</param>
  437. /// <returns></returns>
  438. public static FuncResultList<TResult, RelationalDataReader> FetchResult<TResult>(this RelationalDataReader reader,
  439. Func<dynamic, TResult> selector)
  440. {
  441. List<TResult> list = new();
  442. DataRecordDynamic wrapper = new(reader.DbDataReader);
  443. while (reader.Read())
  444. {
  445. var item = selector(wrapper);
  446. list.Add(item);
  447. }
  448. bool nextResult = reader.DbDataReader.NextResult();
  449. return (out IList<TResult> models, out bool hasNextResult) =>
  450. {
  451. models = list;
  452. hasNextResult = nextResult;
  453. return reader;
  454. };
  455. }
  456. /// <summary>
  457. /// Fetches the result asynchronous.
  458. /// </summary>
  459. /// <typeparam name="TResult">The type of the result.</typeparam>
  460. /// <param name="reader">The reader.</param>
  461. /// <param name="selector">The selector.</param>
  462. /// <param name="cancellationToken">The cancellation token.</param>
  463. /// <returns></returns>
  464. public static async Task<FuncResultList<TResult, RelationalDataReader>> FetchResultAsync<TResult>(this RelationalDataReader reader,
  465. Func<dynamic, TResult> selector,
  466. CancellationToken cancellationToken)
  467. {
  468. List<TResult> list = new();
  469. DataRecordDynamic wrapper = new(reader.DbDataReader);
  470. while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
  471. {
  472. var item = selector(wrapper);
  473. list.Add(item);
  474. }
  475. bool nextResult = await reader.DbDataReader.NextResultAsync(cancellationToken).ConfigureAwait(false);
  476. return (out IList<TResult> models, out bool hasNextResult) =>
  477. {
  478. models = list;
  479. hasNextResult = nextResult;
  480. return reader;
  481. };
  482. }
  483. /// <summary>
  484. /// Fetches the result asynchronous.
  485. /// </summary>
  486. /// <typeparam name="TResult">The type of the result.</typeparam>
  487. /// <param name="reader">The reader.</param>
  488. /// <param name="selector">The selector.</param>
  489. /// <returns></returns>
  490. public static async Task<FuncResultList<TResult, RelationalDataReader>> FetchResultAsync<TResult>(this RelationalDataReader reader,
  491. Func<dynamic, TResult> selector)
  492. {
  493. return await reader.FetchResultAsync(selector, CancellationToken.None).ConfigureAwait(false);
  494. }
  495. /// <summary>
  496. /// Fetches the SQL with multi result set.
  497. /// </summary>
  498. /// <typeparam name="T"></typeparam>
  499. /// <param name="database">The database.</param>
  500. /// <param name="sql">The SQL.</param>
  501. /// <param name="parameters">The parameters.</param>
  502. /// <returns></returns>
  503. public static FuncResultList<T, RelationalDataReader> FetchSql<T>(this DatabaseFacade database,
  504. string sql,
  505. params object[] parameters) where T : class, new()
  506. {
  507. var reader = database.ExecuteReader(sql, parameters);
  508. return reader.FetchResult<T>();
  509. }
  510. /// <summary>
  511. /// Fetches the SQL to dynamic.
  512. /// </summary>
  513. /// <param name="database">The database.</param>
  514. /// <param name="sql">The SQL.</param>
  515. /// <param name="parameters">The parameters.</param>
  516. /// <returns></returns>
  517. public static FuncResultList<dynamic, RelationalDataReader> FetchSqlDynamic(this DatabaseFacade database,
  518. string sql,
  519. params object[] parameters)
  520. {
  521. var reader = database.ExecuteReader(sql, parameters);
  522. return reader.FetchResultDynamic();
  523. }
  524. /// <summary>
  525. /// Fetches the SQL json.
  526. /// </summary>
  527. /// <param name="database">The database.</param>
  528. /// <param name="sql">The SQL.</param>
  529. /// <param name="parameters">The parameters.</param>
  530. /// <returns></returns>
  531. public static StoreResultModel<string, RelationalDataReader> FetchSqlJson(this DatabaseFacade database,
  532. string sql,
  533. params object[] parameters)
  534. {
  535. var reader = database.ExecuteReader(sql, parameters);
  536. return reader.FetchResultJson();
  537. }
  538. /// <summary>
  539. /// Fetches the SQL asynchronous.
  540. /// </summary>
  541. /// <typeparam name="T"></typeparam>
  542. /// <param name="database">The database.</param>
  543. /// <param name="cancellationToken">The cancellation token.</param>
  544. /// <param name="sql">The SQL.</param>
  545. /// <param name="parameters">The parameters.</param>
  546. /// <returns></returns>
  547. public static async Task<FuncResultList<T, RelationalDataReader>> FetchSqlAsync<T>(this DatabaseFacade database,
  548. CancellationToken cancellationToken,
  549. string sql,
  550. params object[] parameters) where T : class, new()
  551. {
  552. var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false);
  553. return await FetchResultAsync<T>(reader, cancellationToken).ConfigureAwait(false);
  554. }
  555. /// <summary>
  556. /// Fetches the SQL asynchronous.
  557. /// </summary>
  558. /// <typeparam name="T"></typeparam>
  559. /// <param name="database">The database.</param>
  560. /// <param name="sql">The SQL.</param>
  561. /// <param name="parameters">The parameters.</param>
  562. /// <returns></returns>
  563. public static async Task<FuncResultList<T, RelationalDataReader>> FetchSqlAsync<T>(this DatabaseFacade database,
  564. string sql,
  565. params object[] parameters) where T : class, new()
  566. {
  567. return await database.FetchSqlAsync<T>(CancellationToken.None, sql, parameters).ConfigureAwait(false);
  568. }
  569. /// <summary>
  570. /// Fetches the SQL.
  571. /// </summary>
  572. /// <typeparam name="TResult">The type of the result.</typeparam>
  573. /// <param name="database">The database.</param>
  574. /// <param name="selector">The selector.</param>
  575. /// <param name="sql">The SQL.</param>
  576. /// <param name="parameters">The parameters.</param>
  577. /// <returns></returns>
  578. public static FuncResultList<TResult, RelationalDataReader> FetchSql<TResult>(this DatabaseFacade database,
  579. Func<dynamic, TResult> selector,
  580. string sql,
  581. params object[] parameters)
  582. {
  583. var reader = database.ExecuteReader(sql, parameters);
  584. return reader.FetchResult(selector);
  585. }
  586. /// <summary>
  587. /// Fetches the SQL asynchronous.
  588. /// </summary>
  589. /// <typeparam name="TResult">The type of the result.</typeparam>
  590. /// <param name="database">The database.</param>
  591. /// <param name="selector">The selector.</param>
  592. /// <param name="cancellationToken">The cancellation token.</param>
  593. /// <param name="sql">The SQL.</param>
  594. /// <param name="parameters">The parameters.</param>
  595. /// <returns></returns>
  596. public static async Task<FuncResultList<TResult, RelationalDataReader>> FetchSqlAsync<TResult>(this DatabaseFacade database,
  597. Func<dynamic, TResult> selector,
  598. CancellationToken cancellationToken,
  599. string sql,
  600. params object[] parameters)
  601. {
  602. var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false);
  603. return await FetchResultAsync(reader, selector, cancellationToken).ConfigureAwait(false);
  604. }
  605. /// <summary>
  606. /// Fetches the SQL asynchronous.
  607. /// </summary>
  608. /// <typeparam name="TResult">The type of the result.</typeparam>
  609. /// <param name="database">The database.</param>
  610. /// <param name="selector">The selector.</param>
  611. /// <param name="sql">The SQL.</param>
  612. /// <param name="parameters">The parameters.</param>
  613. /// <returns></returns>
  614. public static async Task<FuncResultList<TResult, RelationalDataReader>> FetchSqlAsync<TResult>(this DatabaseFacade database,
  615. Func<dynamic, TResult> selector,
  616. string sql,
  617. params object[] parameters)
  618. {
  619. return await database.FetchSqlAsync(selector, CancellationToken.None, sql, parameters).ConfigureAwait(false);
  620. }
  621. /// <summary>
  622. /// Selects the SQL.
  623. /// </summary>
  624. /// <typeparam name="T"></typeparam>
  625. /// <param name="database">The database.</param>
  626. /// <param name="sql">The SQL.</param>
  627. /// <param name="parameters">The parameters.</param>
  628. /// <returns></returns>
  629. public static IList<T> SelectSql<T>(this DatabaseFacade database,
  630. string sql,
  631. params object[] parameters) where T : class, new()
  632. {
  633. var reader = database.ExecuteReader(sql, parameters);
  634. bool hasNextResult = false;
  635. reader.FetchResult<T>()(out var list, out hasNextResult);
  636. return list;
  637. }
  638. /// <summary>
  639. /// Selects the SQL asynchronous.
  640. /// </summary>
  641. /// <typeparam name="T"></typeparam>
  642. /// <param name="database">The database.</param>
  643. /// <param name="cancellationToken">The cancellation token.</param>
  644. /// <param name="sql">The SQL.</param>
  645. /// <param name="parameters">The parameters.</param>
  646. /// <returns></returns>
  647. public static async Task<IList<T>> SelectSqlAsync<T>(this DatabaseFacade database,
  648. CancellationToken cancellationToken,
  649. string sql,
  650. params object[] parameters) where T : class, new()
  651. {
  652. var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false);
  653. bool hasNextResult = false;
  654. (await FetchResultAsync<T>(reader, cancellationToken).ConfigureAwait(false))(out var list, out hasNextResult);
  655. return list;
  656. }
  657. /// <summary>
  658. /// Selects the SQL asynchronous.
  659. /// </summary>
  660. /// <typeparam name="T"></typeparam>
  661. /// <param name="database">The database.</param>
  662. /// <param name="sql">The SQL.</param>
  663. /// <param name="parameters">The parameters.</param>
  664. /// <returns></returns>
  665. public static async Task<IList<T>> SelectSqlAsync<T>(this DatabaseFacade database,
  666. string sql,
  667. params object[] parameters) where T : class, new()
  668. {
  669. return await database.SelectSqlAsync<T>(CancellationToken.None, sql, parameters).ConfigureAwait(false);
  670. }
  671. /// <summary>
  672. /// Selects the SQL.
  673. /// </summary>
  674. /// <typeparam name="TResult">The type of the result.</typeparam>
  675. /// <param name="database">The database.</param>
  676. /// <param name="selector">The selector.</param>
  677. /// <param name="sql">The SQL.</param>
  678. /// <param name="parameters">The parameters.</param>
  679. /// <returns></returns>
  680. public static IList<TResult> SelectSql<TResult>(this DatabaseFacade database,
  681. Func<dynamic, TResult> selector,
  682. string sql,
  683. params object[] parameters)
  684. {
  685. var reader = database.ExecuteReader(sql, parameters);
  686. bool hasNextResult = false;
  687. reader.FetchResult(selector)(out var list, out hasNextResult);
  688. return list;
  689. }
  690. /// <summary>
  691. /// Selects the SQL asynchronous.
  692. /// </summary>
  693. /// <typeparam name="TResult">The type of the result.</typeparam>
  694. /// <param name="database">The database.</param>
  695. /// <param name="cancellationToken">The cancellation token.</param>
  696. /// <param name="selector">The selector.</param>
  697. /// <param name="sql">The SQL.</param>
  698. /// <param name="parameters">The parameters.</param>
  699. /// <returns></returns>
  700. public static async Task<IList<TResult>> SelectSqlAsync<TResult>(this DatabaseFacade database,
  701. Func<dynamic, TResult> selector,
  702. CancellationToken cancellationToken,
  703. string sql,
  704. params object[] parameters)
  705. {
  706. var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false);
  707. bool hasNextResult = false;
  708. (await FetchResultAsync(reader, selector, cancellationToken).ConfigureAwait(false))(out var list, out hasNextResult);
  709. return list;
  710. }
  711. /// <summary>
  712. /// Selects the SQL asynchronous.
  713. /// </summary>
  714. /// <typeparam name="TResult">The type of the result.</typeparam>
  715. /// <param name="database">The database.</param>
  716. /// <param name="selector">The selector.</param>
  717. /// <param name="sql">The SQL.</param>
  718. /// <param name="parameters">The parameters.</param>
  719. /// <returns></returns>
  720. public static async Task<IList<TResult>> SelectSqlAsync<TResult>(this DatabaseFacade database,
  721. Func<dynamic, TResult> selector,
  722. string sql,
  723. params object[] parameters)
  724. {
  725. return await database.SelectSqlAsync(selector, CancellationToken.None, sql, parameters).ConfigureAwait(false);
  726. }
  727. /// <summary>
  728. /// Selects the SQL to dataset and output dictionary.
  729. /// </summary>
  730. /// <param name="database">The database.</param>
  731. /// <param name="sql">The SQL.</param>
  732. /// <param name="parameters">The parameters.</param>
  733. /// <returns></returns>
  734. public static StoreResultModel<DataSet, Dictionary<string, object>> SelectSqlToDataSetOutput(this DatabaseFacade database,
  735. string sql,
  736. params object[] parameters)
  737. {
  738. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  739. var reader = database.ExecuteReader(sql, fixParams);
  740. var data = reader.FetchToDataSet();
  741. var result = ParameterUtils.GatherOutputParameters(data.Tables.Count, fixParams);
  742. result.ForEach(p => data.ExtendedProperties[p.Key] = p.Value);
  743. return (out DataSet models) =>
  744. {
  745. models = data;
  746. return result;
  747. };
  748. }
  749. /// <summary>
  750. /// Selects the SQL to data set output asynchronous.
  751. /// </summary>
  752. /// <param name="database">The database.</param>
  753. /// <param name="cancellationToken">The cancellation token.</param>
  754. /// <param name="sql">The SQL.</param>
  755. /// <param name="parameters">The parameters.</param>
  756. /// <returns></returns>
  757. public static async Task<StoreResultModel<DataSet, Dictionary<string, object>>> SelectSqlToDataSetOutputAsync(this DatabaseFacade database,
  758. CancellationToken cancellationToken,
  759. string sql,
  760. params object[] parameters)
  761. {
  762. var fixParams = ParameterUtils.GetParameters(false, parameters);
  763. var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false);
  764. var data = await reader.FetchToDataSetAsync();
  765. var result = ParameterUtils.GatherOutputParameters(data.Tables.Count, fixParams);
  766. return (out DataSet models) =>
  767. {
  768. models = data;
  769. return result;
  770. };
  771. }
  772. /// <summary>
  773. /// Selects the SQL to data set asynchronous.
  774. /// </summary>
  775. /// <param name="database">The database.</param>
  776. /// <param name="sql">The SQL.</param>
  777. /// <param name="parameters">The parameters.</param>
  778. /// <returns></returns>
  779. public static DataSet SelectSqlToDataSet(this DatabaseFacade database,
  780. string sql,
  781. params object[] parameters)
  782. {
  783. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  784. var reader = database.ExecuteReader(sql, fixParams);
  785. var dataSet = reader.FetchToDataSet();
  786. var result = ParameterUtils.GatherOutputParameters(dataSet.Tables.Count, fixParams);
  787. result.ForEach(p => dataSet.ExtendedProperties[p.Key] = p.Value);
  788. return dataSet;
  789. }
  790. /// <summary>
  791. /// Selects the SQL to data set asynchronous.
  792. /// </summary>
  793. /// <param name="database">The database.</param>
  794. /// <param name="cancellationToken">The cancellation token.</param>
  795. /// <param name="sql">The SQL.</param>
  796. /// <param name="parameters">The parameters.</param>
  797. /// <returns></returns>
  798. public static async Task<DataSet> SelectSqlToDataSetAsync(this DatabaseFacade database,
  799. CancellationToken cancellationToken,
  800. string sql,
  801. params object[] parameters)
  802. {
  803. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  804. var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false);
  805. var dataSet = await reader.FetchToDataSetAsync();
  806. var result = ParameterUtils.GatherOutputParameters(dataSet.Tables.Count, fixParams);
  807. result.ForEach(p => dataSet.ExtendedProperties[p.Key] = p.Value);
  808. return dataSet;
  809. }
  810. /// <summary>
  811. /// Executes the store procedure.
  812. /// </summary>
  813. /// <param name="database">The database.</param>
  814. /// <param name="storeProcedure">The store procedure.</param>
  815. /// <param name="parameters">The parameters.</param>
  816. /// <returns></returns>
  817. public static Dictionary<string, object> ExecStoreProcedure(this DatabaseFacade database,
  818. string storeProcedure,
  819. params object[] parameters)
  820. {
  821. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  822. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  823. int rowsAffected = database.ExecuteNonQuery(queryString, fixParams);
  824. var result = ParameterUtils.GatherOutputParameters(rowsAffected, fixParams);
  825. return result;
  826. }
  827. /// <summary>
  828. /// Executes the store procedure asynchronous.
  829. /// </summary>
  830. /// <param name="database">The database.</param>
  831. /// <param name="cancellationToken">The cancellation token.</param>
  832. /// <param name="storeProcedure">The store procedure.</param>
  833. /// <param name="parameters">The parameters.</param>
  834. /// <returns></returns>
  835. public static async Task<Dictionary<string, object>> ExecStoreProcedureAsync(this DatabaseFacade database,
  836. CancellationToken cancellationToken,
  837. string storeProcedure,
  838. params object[] parameters)
  839. {
  840. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  841. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  842. int rowsAffected = await database.ExecuteNonQueryAsync(queryString, cancellationToken, fixParams).ConfigureAwait(false);
  843. var result = ParameterUtils.GatherOutputParameters(rowsAffected, fixParams);
  844. return result;
  845. }
  846. /// <summary>
  847. /// Executes the store procedure asynchronous.
  848. /// </summary>
  849. /// <param name="database">The database.</param>
  850. /// <param name="storeProcedure">The store procedure.</param>
  851. /// <param name="parameters">The parameters.</param>
  852. /// <returns></returns>
  853. public static async Task<Dictionary<string, object>> ExecStoreProcedureAsync(this DatabaseFacade database,
  854. string storeProcedure,
  855. params object[] parameters)
  856. {
  857. return await database.ExecStoreProcedureAsync(CancellationToken.None, storeProcedure, storeProcedure, parameters).ConfigureAwait(false);
  858. }
  859. /// <summary>
  860. /// Stores the procedure get data set.
  861. /// </summary>
  862. /// <param name="database">The database.</param>
  863. /// <param name="storeProcedure">The store procedure.</param>
  864. /// <param name="parameters">The parameters.</param>
  865. /// <returns></returns>
  866. public static DataSet StoreProcedureGetDataSet(this DatabaseFacade database,
  867. string storeProcedure,
  868. params object[] parameters)
  869. {
  870. var fixParams = ParameterUtils.GetParameters(false, parameters);
  871. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  872. var reader = database.ExecuteReader(queryString, fixParams);
  873. var dataSet = reader.FetchToDataSet(parameters: fixParams);
  874. return dataSet;
  875. }
  876. /// <summary>
  877. /// Stores the procedure get.
  878. /// </summary>
  879. /// <typeparam name="T"></typeparam>
  880. /// <param name="database">The database.</param>
  881. /// <param name="storeProcedure">The store procedure.</param>
  882. /// <param name="parameters">The parameters.</param>
  883. /// <returns></returns>
  884. public static StoreResultList<T, Dictionary<string, object>> StoreProcedureGet<T>(this DatabaseFacade database,
  885. string storeProcedure,
  886. params object[] parameters) where T : class, new()
  887. {
  888. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  889. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  890. var list = database.SelectSql<T>(queryString, fixParams);
  891. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  892. return (out IList<T> models) =>
  893. {
  894. models = list;
  895. return result;
  896. };
  897. }
  898. /// <summary>
  899. /// Stores the procedure get dynamic.
  900. /// </summary>
  901. /// <param name="database">The database.</param>
  902. /// <param name="storeProcedure">The store procedure.</param>
  903. /// <param name="parameters">The parameters.</param>
  904. /// <returns></returns>
  905. /// <remarks></remarks>
  906. public static StoreResultList<dynamic, Dictionary<string, object>> StoreProcedureGet(this DatabaseFacade database,
  907. string storeProcedure,
  908. params object[] parameters)
  909. {
  910. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  911. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  912. var reader = database.ExecuteReader(queryString, fixParams);
  913. var list = reader.FetchToDynamic();
  914. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  915. return (out IList<dynamic> models) =>
  916. {
  917. models = list;
  918. return result;
  919. };
  920. }
  921. /// <summary>
  922. /// Stores the procedure get asynchronous.
  923. /// </summary>
  924. /// <typeparam name="T"></typeparam>
  925. /// <param name="database">The database.</param>
  926. /// <param name="cancellationToken">The cancellation token.</param>
  927. /// <param name="storeProcedure">The store procedure.</param>
  928. /// <param name="parameters">The parameters.</param>
  929. /// <returns></returns>
  930. public static async Task<StoreResultList<T, Dictionary<string, object>>> StoreProcedureGetAsync<T>(this DatabaseFacade database,
  931. CancellationToken cancellationToken,
  932. string storeProcedure,
  933. params object[] parameters) where T : class, new()
  934. {
  935. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  936. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  937. var list = await database.SelectSqlAsync<T>(cancellationToken, queryString, fixParams).ConfigureAwait(false);
  938. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  939. return (out IList<T> models) =>
  940. {
  941. models = list;
  942. return result;
  943. };
  944. }
  945. /// <summary>
  946. /// Stores the procedure get asynchronous.
  947. /// </summary>
  948. /// <typeparam name="T"></typeparam>
  949. /// <param name="database">The database.</param>
  950. /// <param name="storeProcedure">The store procedure.</param>
  951. /// <param name="parameters">The parameters.</param>
  952. /// <returns></returns>
  953. public static async Task<StoreResultList<T, Dictionary<string, object>>> StoreProcedureGetAsync<T>(this DatabaseFacade database,
  954. string storeProcedure,
  955. params object[] parameters) where T : class, new()
  956. {
  957. return await database.StoreProcedureGetAsync<T>(CancellationToken.None, storeProcedure, parameters).ConfigureAwait(false);
  958. }
  959. /// <summary>
  960. /// Stores the procedure get.
  961. /// </summary>
  962. /// <typeparam name="TResult">The type of the result.</typeparam>
  963. /// <param name="database">The database.</param>
  964. /// <param name="selector">The selector.</param>
  965. /// <param name="storeProcedure">The store procedure.</param>
  966. /// <param name="parameters">The parameters.</param>
  967. /// <returns></returns>
  968. public static StoreResultList<TResult, Dictionary<string, object>> StoreProcedureGet<TResult>(this DatabaseFacade database,
  969. Func<dynamic, TResult> selector,
  970. string storeProcedure,
  971. params object[] parameters)
  972. {
  973. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  974. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  975. var list = database.SelectSql(selector, queryString, fixParams);
  976. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  977. return (out IList<TResult> models) =>
  978. {
  979. models = list;
  980. return result;
  981. };
  982. }
  983. /// <summary>
  984. /// Stores the procedure get asynchronous.
  985. /// </summary>
  986. /// <typeparam name="TResult">The type of the result.</typeparam>
  987. /// <param name="database">The database.</param>
  988. /// <param name="selector">The selector.</param>
  989. /// <param name="cancellationToken">The cancellation token.</param>
  990. /// <param name="storeProcedure">The store procedure.</param>
  991. /// <param name="parameters">The parameters.</param>
  992. /// <returns></returns>
  993. public static async Task<StoreResultList<TResult, Dictionary<string, object>>> StoreProcedureGetAsync<TResult>(this DatabaseFacade database,
  994. Func<dynamic, TResult> selector,
  995. CancellationToken cancellationToken,
  996. string storeProcedure,
  997. params object[] parameters)
  998. {
  999. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  1000. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  1001. var list = await database.SelectSqlAsync(selector, cancellationToken, queryString, fixParams).ConfigureAwait(false);
  1002. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  1003. return (out IList<TResult> models) =>
  1004. {
  1005. models = list;
  1006. return result;
  1007. };
  1008. }
  1009. /// <summary>
  1010. /// Stores the procedure get asynchronous.
  1011. /// </summary>
  1012. /// <typeparam name="TResult">The type of the result.</typeparam>
  1013. /// <param name="database">The database.</param>
  1014. /// <param name="selector">The selector.</param>
  1015. /// <param name="storeProcedure">The store procedure.</param>
  1016. /// <param name="parameters">The parameters.</param>
  1017. /// <returns></returns>
  1018. public static async Task<StoreResultList<TResult, Dictionary<string, object>>> StoreProcedureGetAsync<TResult>(this DatabaseFacade database,
  1019. Func<dynamic, TResult> selector,
  1020. string storeProcedure,
  1021. params object[] parameters)
  1022. {
  1023. return await database.StoreProcedureGetAsync(selector, storeProcedure, parameters).ConfigureAwait(false);
  1024. }
  1025. /// <summary>
  1026. /// Fetches the store procedure.
  1027. /// </summary>
  1028. /// <typeparam name="T"></typeparam>
  1029. /// <param name="database">The database.</param>
  1030. /// <param name="storeProcedure">The store procedure.</param>
  1031. /// <param name="parameters">The parameters.</param>
  1032. /// <returns></returns>
  1033. public static StoreResultList<T, Dictionary<string, object>, RelationalDataReader> FetchStoreProcedure<T>(this DatabaseFacade database,
  1034. string storeProcedure,
  1035. params object[] parameters) where T : class, new()
  1036. {
  1037. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  1038. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  1039. bool nextResult = false;
  1040. var reader = database.FetchSql<T>(queryString, fixParams)(out var list, out nextResult);
  1041. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  1042. return (out IList<T> models, out Dictionary<string, object> outVars, out bool hasNextResult) =>
  1043. {
  1044. models = list;
  1045. outVars = result;
  1046. hasNextResult = nextResult;
  1047. return reader;
  1048. };
  1049. }
  1050. /// <summary>
  1051. /// Fetches the store procedure.
  1052. /// </summary>
  1053. /// <param name="database">The database.</param>
  1054. /// <param name="storeProcedure">The store procedure.</param>
  1055. /// <param name="parameters">The parameters.</param>
  1056. /// <returns></returns>
  1057. /// <remarks></remarks>
  1058. public static StoreResultList<dynamic, Dictionary<string, object>, RelationalDataReader> FetchStoreProcedureDynamic(this DatabaseFacade database,
  1059. string storeProcedure,
  1060. params object[] parameters)
  1061. {
  1062. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  1063. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  1064. bool nextResult = false;
  1065. var reader = database.FetchSqlDynamic(queryString, fixParams)(out var list, out nextResult);
  1066. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  1067. return (out IList<dynamic> models, out Dictionary<string, object> outVars, out bool hasNextResult) =>
  1068. {
  1069. models = list;
  1070. outVars = result;
  1071. hasNextResult = nextResult;
  1072. return reader;
  1073. };
  1074. }
  1075. /// <summary>
  1076. /// Fetches the store procedure json.
  1077. /// </summary>
  1078. /// <param name="database">The database.</param>
  1079. /// <param name="storeProcedure">The store procedure.</param>
  1080. /// <param name="parameters">The parameters.</param>
  1081. /// <returns></returns>
  1082. public static string FetchStoreProcedureJson(this DatabaseFacade database,
  1083. string storeProcedure,
  1084. params object[] parameters)
  1085. {
  1086. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  1087. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  1088. var reader = database.FetchSqlJson(queryString, fixParams)(out string data);
  1089. return data;
  1090. }
  1091. /// <summary>
  1092. /// Fetches the store procedure asynchronous.
  1093. /// </summary>
  1094. /// <typeparam name="T"></typeparam>
  1095. /// <param name="database">The database.</param>
  1096. /// <param name="cancellationToken">The cancellation token.</param>
  1097. /// <param name="storeProcedure">The store procedure.</param>
  1098. /// <param name="parameters">The parameters.</param>
  1099. /// <returns></returns>
  1100. public static async Task<StoreResultList<T, Dictionary<string, object>, RelationalDataReader>> FetchStoreProcedureAsync<T>(this DatabaseFacade database,
  1101. CancellationToken cancellationToken,
  1102. string storeProcedure,
  1103. params object[] parameters) where T : class, new()
  1104. {
  1105. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  1106. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  1107. bool nextResult = false;
  1108. var reader = (await database.FetchSqlAsync<T>(cancellationToken, queryString, fixParams).ConfigureAwait(false))(out var list, out nextResult);
  1109. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  1110. return (out IList<T> models, out Dictionary<string, object> outVars, out bool hasNextResult) =>
  1111. {
  1112. models = list;
  1113. outVars = result;
  1114. hasNextResult = nextResult;
  1115. return reader;
  1116. };
  1117. }
  1118. /// <summary>
  1119. /// Fetches the store procedure asynchronous.
  1120. /// </summary>
  1121. /// <typeparam name="T"></typeparam>
  1122. /// <param name="database">The database.</param>
  1123. /// <param name="storeProcedure">The store procedure.</param>
  1124. /// <param name="parameters">The parameters.</param>
  1125. /// <returns></returns>
  1126. public static async Task<StoreResultList<T, Dictionary<string, object>, RelationalDataReader>> FetchStoreProcedureAsync<T>(this DatabaseFacade database,
  1127. string storeProcedure,
  1128. params object[] parameters) where T : class, new()
  1129. {
  1130. return await database.FetchStoreProcedureAsync<T>(CancellationToken.None, storeProcedure, parameters).ConfigureAwait(false);
  1131. }
  1132. /// <summary>
  1133. /// Fetches the store procedure.
  1134. /// </summary>
  1135. /// <typeparam name="TResult">The type of the result.</typeparam>
  1136. /// <param name="database">The database.</param>
  1137. /// <param name="selector">The selector.</param>
  1138. /// <param name="storeProcedure">The store procedure.</param>
  1139. /// <param name="parameters">The parameters.</param>
  1140. /// <returns></returns>
  1141. public static StoreResultList<TResult, Dictionary<string, object>, RelationalDataReader> FetchStoreProcedure<TResult>(this DatabaseFacade database,
  1142. Func<dynamic, TResult> selector,
  1143. string storeProcedure,
  1144. params object[] parameters)
  1145. {
  1146. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  1147. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  1148. bool nextResult = false;
  1149. var reader = database.FetchSql(selector, queryString, fixParams)(out var list, out nextResult);
  1150. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  1151. return (out IList<TResult> models, out Dictionary<string, object> outVars, out bool hasNextResult) =>
  1152. {
  1153. models = list;
  1154. outVars = result;
  1155. hasNextResult = nextResult;
  1156. return reader;
  1157. };
  1158. }
  1159. /// <summary>
  1160. /// Fetches the store procedure asynchronous.
  1161. /// </summary>
  1162. /// <typeparam name="TResult">The type of the result.</typeparam>
  1163. /// <param name="database">The database.</param>
  1164. /// <param name="selector">The selector.</param>
  1165. /// <param name="cancellationToken">The cancellation token.</param>
  1166. /// <param name="storeProcedure">The store procedure.</param>
  1167. /// <param name="parameters">The parameters.</param>
  1168. /// <returns></returns>
  1169. public static async Task<StoreResultList<TResult, Dictionary<string, object>, RelationalDataReader>> FetchStoreProcedureAsync<TResult>(this DatabaseFacade database,
  1170. Func<dynamic, TResult> selector,
  1171. CancellationToken cancellationToken,
  1172. string storeProcedure,
  1173. params object[] parameters)
  1174. {
  1175. var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters));
  1176. string queryString = GetExecStoreProcedureString(storeProcedure, fixParams);
  1177. bool nextResult = false;
  1178. var reader = (await database.FetchSqlAsync(selector, cancellationToken, queryString, fixParams).ConfigureAwait(false))(out var list, out nextResult);
  1179. var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams);
  1180. return (out IList<TResult> models, out Dictionary<string, object> outVars, out bool hasNextResult) =>
  1181. {
  1182. models = list;
  1183. outVars = result;
  1184. hasNextResult = nextResult;
  1185. return reader;
  1186. };
  1187. }
  1188. }
  1189. }