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