using System; using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; using EasyDevCore.Common; using System.Data; using System.Runtime.CompilerServices; using System.Dynamic; using System.Collections; using System.Reflection; using System.Collections.Concurrent; using EasyDevCore.Database; using System.Transactions; namespace EasyDevCore.Database { /// /// /// /// The type of the model. /// The type of the result. /// The models. /// if set to true [has next result]. /// public delegate TResult FuncResultList(out IList models, out bool hasNextResult); /// /// /// /// The type of the model. /// The type of the result. /// The models. /// public delegate TResult StoreResultList(out IList models); /// /// /// /// The type of the model. /// The type of the result. /// The models. /// public delegate TResult StoreResultModel(out TModel models); /// /// /// /// The type of the model. /// The type of the out. /// The type of the result. /// The models. /// The out vars. /// if set to true [has next result]. /// public delegate TResult StoreResultList(out IList models, out TOut outVars, out bool hasNextResult); /// /// /// public static class EasyDatabaseFacadeExtensions { private static ConcurrentDictionary _ParameterTypesCache = new(); private static string GetExecStoreProcedureString(string storeProcedure, IEnumerable parameters) { return @"--" + string.Join(",", parameters.OfType().Where(p => p.ParameterName.In("ApplicationID", "UserID", "HostName", "ScreenID")).Select(p => $@"{p.ParameterName}={p.Value}")) + @" EXEC @RETURN_VALUE = " + storeProcedure + " " + string.Join(",", parameters.OfType().Where(p => !p.ParameterName.In("RETURN_VALUE", "RETURN_ROWS_EFFECTED")).Select(p => $"@{p.ParameterName} = @{p.ParameterName}" + (p.Direction.In(ParameterDirection.Output, ParameterDirection.InputOutput) ? " OUTPUT" : ""))); } /// /// Synchronizes the output parameters. /// /// The in parameters. /// The out parameters. private static void SyncOutputParameters(object inParams, IEnumerable outParams) { IEnumerable fixInParams = null; if (inParams == outParams) return; if (inParams is object[] && ((object[])inParams).Length == 1 && ((object[])inParams)[0] is EasyDbParameterCollection) { fixInParams = (EasyDbParameterCollection)((object[])inParams)[0]; } if (inParams is IEnumerable) { fixInParams = (IEnumerable)inParams; } if (fixInParams == null) return; var synchList = from pIn in fixInParams join pOut in outParams on pIn.ParameterName equals pOut.ParameterName where pIn.Direction.In(ParameterDirection.Output, ParameterDirection.InputOutput, ParameterDirection.ReturnValue) select new { pIn, pOut.Value }; synchList.ForEach(v => v.pIn.Value = v.Value); } /// /// Creates the parameter. /// /// The database. /// The parameter. /// public static EasyDbParameter CreateParameter(this DatabaseFacade database, EasyDbParameter parameter) { if (!_ParameterTypesCache.TryGetValue(database.ProviderName, out Type type)) { var command = database.GetDbConnection().CreateCommand(); type = command.CreateParameter().GetType(); _ParameterTypesCache.TryAdd(database.ProviderName, type); } EasyDbParameter param = (EasyDbParameter)type.CreateInstance(parameter.ParameterName, parameter.Value ?? DBNull.Value); param.Direction = parameter.Direction; param.Scale = parameter.Scale != 0 ? parameter.Scale : param.Scale; param.Precision = parameter.Precision != 0 ? parameter.Precision : param.Precision; param.Size = parameter.Precision != 0 ? parameter.Precision : param.Precision; if (param.Value is DateTime && ((DateTime)param.Value).Date <= DateTime.Parse("1900/01/01")) { param.Value = DateTime.Parse("1900/01/01"); } if (param.Direction == ParameterDirection.InputOutput && param.Value.GetType() == typeof(decimal)) { param.Precision = 28; param.Scale = 8; } if (param.DbType.In(DbType.String, DbType.AnsiString, DbType.StringFixedLength, DbType.AnsiStringFixedLength) && param.Direction.In(ParameterDirection.InputOutput, ParameterDirection.Output)) { param.Size = -1; } return param; } /// /// Converts the parameters. /// /// The database.The database. /// The parameters.The parameters. /// ///
///
private static IEnumerable ConvertParameters(DatabaseFacade database, EasyDbParameterCollection parameters) { IEnumerable result = null; if (parameters != null && parameters.Any() && !(parameters.First() is EasyDbParameter)) { result = parameters; foreach (var p in parameters.Where(dp => !dp.Direction.In(ParameterDirection.InputOutput, ParameterDirection.Output) && (dp.Value == null || dp.Value == DBNull.Value)).ToArray()) { parameters.Remove(p.ParameterName); } } else { result = new EasyDbParameterCollection(); if (parameters != null) { foreach (EasyDbParameter param in parameters) { if (param.Direction.In(ParameterDirection.InputOutput, ParameterDirection.Output) || param.Value != DBNull.Value && param.Value != null) { ((EasyDbParameterCollection)result).Add(database.CreateParameter(param)); } } } } return result; } /// /// Gets the context. /// /// The database. /// public static DbContext GetContext(this DatabaseFacade database) { object internalSet = database .GetType() .GetField("_internalSet", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(database); object internalContext = internalSet .GetType() .BaseType .GetField("_internalContext", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(internalSet); return (DbContext)internalContext .GetType() .GetProperty("Owner", BindingFlags.Instance | BindingFlags.Public) .GetValue(internalContext, null); } /// /// Executes the non query asynchronous. /// /// The database. /// The cancellation token. /// The SQL. /// The parameters. /// public static Task ExecuteNonQueryAsync(this DatabaseFacade database, CancellationToken cancellationToken, string sql, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); var concurrencyDetector = database.GetService(); using (concurrencyDetector.EnterCriticalSection()) { var rawSqlCommand = database.GetService().Build(sql, fixParams); var paramObject = new RelationalCommandParameterObject(database.GetService(), rawSqlCommand.ParameterValues, null, null, null); return rawSqlCommand.RelationalCommand.ExecuteNonQueryAsync(paramObject, cancellationToken).ContinueWith(t => { SyncOutputParameters(parameters, fixParams); return t.Result; }); } } /// /// Executes the non query asynchronous. /// /// The database. /// The SQL. /// The parameters. /// public static Task ExecuteNonQueryAsync(this DatabaseFacade database, string sql, params object[] parameters) { return database.ExecuteNonQueryAsync(CancellationToken.None, sql, parameters); } /// /// Executes the non query. /// /// The database. /// The SQL. /// The parameters. /// public static int ExecuteNonQuery(this DatabaseFacade database, string sql, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); var concurrencyDetector = database.GetService(); using (concurrencyDetector.EnterCriticalSection()) { var rawSqlCommand = database.GetService().Build(sql, fixParams); var paramObject = new RelationalCommandParameterObject(database.GetService(), rawSqlCommand.ParameterValues, null, null, null); var result = rawSqlCommand.RelationalCommand.ExecuteNonQuery(paramObject); SyncOutputParameters(parameters, fixParams); return result; } } /// /// Executes the scalar. /// /// The database. /// The SQL. /// The parameters. /// public static object ExecuteScalar(this DatabaseFacade database, string sql, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); var concurrencyDetector = database.GetService(); using (concurrencyDetector.EnterCriticalSection()) { var rawSqlCommand = database.GetService().Build(sql, fixParams); var paramObject = new RelationalCommandParameterObject(database.GetService(), rawSqlCommand.ParameterValues, null, null, null); var result = rawSqlCommand.RelationalCommand.ExecuteScalar(paramObject); SyncOutputParameters(parameters, fixParams); return result; } } /// /// Executes the scalar asynchronous. /// /// The database. /// The SQL. /// The parameters. /// public static Task ExecuteScalarAsync(this DatabaseFacade database, string sql, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); var concurrencyDetector = database.GetService(); using (concurrencyDetector.EnterCriticalSection()) { var rawSqlCommand = database.GetService().Build(sql, fixParams); var paramObject = new RelationalCommandParameterObject(database.GetService(), rawSqlCommand.ParameterValues, null, null, null); var result = rawSqlCommand.RelationalCommand.ExecuteScalarAsync(paramObject); SyncOutputParameters(parameters, fixParams); return result; } } /// /// Executes the reader. /// /// The database facade. /// The SQL. /// The parameters. /// public static RelationalDataReader ExecuteReader(this DatabaseFacade database, string sql, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); var concurrencyDetector = database.GetService(); using (concurrencyDetector.EnterCriticalSection()) { var rawSqlCommand = database.GetService().Build(sql, fixParams); var paramObject = new RelationalCommandParameterObject(database.GetService(), rawSqlCommand.ParameterValues, null, null, null); var result = rawSqlCommand.RelationalCommand.ExecuteReader(paramObject); SyncOutputParameters(parameters, fixParams); return result; } } /// /// Executes the reader asynchronous. /// /// The database facade. /// The cancellation token. /// The SQL. /// The parameters. /// public static Task ExecuteReaderAsync(this DatabaseFacade database, CancellationToken cancellationToken, string sql, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); var concurrencyDetector = database.GetService(); using (concurrencyDetector.EnterCriticalSection()) { var rawSqlCommand = database.GetService().Build(sql, fixParams); var paramObject = new RelationalCommandParameterObject(database.GetService(), rawSqlCommand.ParameterValues, null, null, null); return rawSqlCommand.RelationalCommand.ExecuteReaderAsync(paramObject, cancellationToken).ContinueWith(t => { SyncOutputParameters(parameters, fixParams); return t.Result; }); } } /// /// Executes the reader asynchronous. /// /// The database. /// The SQL. /// The parameters. /// public static Task ExecuteReaderAsync(this DatabaseFacade database, string sql, params object[] parameters) { return database.ExecuteReaderAsync(CancellationToken.None, sql, parameters); } /// /// Fetches the result. /// /// /// The reader. /// public static FuncResultList FetchResult(this RelationalDataReader reader) where T : class, new() { List list = new(); var mapper = new DbDataReaderMapper(reader); mapper.Map(row => list.Add(row)); var nextResult = reader.DbDataReader.NextResult(); if (!nextResult) reader.DbDataReader.Close(); return (out IList models, out bool hasNextResult) => { models = list; hasNextResult = nextResult; return reader; }; } /// /// Fetches the result json. /// /// The reader. /// public static StoreResultModel FetchResultJson(this RelationalDataReader reader) { var json = reader.DbDataReader.FetchToJson(); var nextResult = reader.DbDataReader.NextResult(); if (!nextResult) reader.DbDataReader.Close(); return (out string models) => { models = json; return reader; }; } /// /// Fetches the result dynamic. /// /// The reader. /// /// public static FuncResultList FetchResultDynamic(this RelationalDataReader reader) { var list = reader.DbDataReader.FetchToDynamic(); var nextResult = reader.DbDataReader.NextResult(); if (!nextResult) reader.DbDataReader.Close(); return (out IList models, out bool hasNextResult) => { models = list; hasNextResult = nextResult; return reader; }; } /// /// Fetches the result asynchronous. /// /// /// The reader. /// The cancellation token. /// public static async Task> FetchResultAsync(this RelationalDataReader reader, CancellationToken cancellationToken) where T : class, new() { List list = new(); var mapper = new DbDataReaderMapper(reader); await mapper.MapAsync(row => list.Add(row), cancellationToken).ConfigureAwait(false); bool nextResult = await reader.DbDataReader.NextResultAsync(cancellationToken).ConfigureAwait(false); if (!nextResult) await reader.DbDataReader.CloseAsync(); return (out IList models, out bool hasNextResult) => { models = list; hasNextResult = nextResult; return reader; }; } /// /// Fetches the result asynchronous. /// /// /// The reader. /// public static async Task> FetchResultAsync(this RelationalDataReader reader) where T : class, new() { return await reader.FetchResultAsync(CancellationToken.None).ConfigureAwait(false); } /// /// Fetches the result. /// /// The type of the result. /// The reader. /// The selector. /// public static FuncResultList FetchResult(this RelationalDataReader reader, Func selector) { List list = new(); DataRecordDynamic wrapper = new(reader.DbDataReader); while (reader.Read()) { var item = selector(wrapper); list.Add(item); } bool nextResult = reader.DbDataReader.NextResult(); return (out IList models, out bool hasNextResult) => { models = list; hasNextResult = nextResult; return reader; }; } /// /// Fetches the result asynchronous. /// /// The type of the result. /// The reader. /// The selector. /// The cancellation token. /// public static async Task> FetchResultAsync(this RelationalDataReader reader, Func selector, CancellationToken cancellationToken) { List list = new(); DataRecordDynamic wrapper = new(reader.DbDataReader); while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) { var item = selector(wrapper); list.Add(item); } bool nextResult = await reader.DbDataReader.NextResultAsync(cancellationToken).ConfigureAwait(false); return (out IList models, out bool hasNextResult) => { models = list; hasNextResult = nextResult; return reader; }; } /// /// Fetches the result asynchronous. /// /// The type of the result. /// The reader. /// The selector. /// public static async Task> FetchResultAsync(this RelationalDataReader reader, Func selector) { return await reader.FetchResultAsync(selector, CancellationToken.None).ConfigureAwait(false); } /// /// Fetches the SQL with multi result set. /// /// /// The database. /// The SQL. /// The parameters. /// public static FuncResultList FetchSql(this DatabaseFacade database, string sql, params object[] parameters) where T : class, new() { var reader = database.ExecuteReader(sql, parameters); return reader.FetchResult(); } /// /// Fetches the SQL to dynamic. /// /// The database. /// The SQL. /// The parameters. /// public static FuncResultList FetchSqlDynamic(this DatabaseFacade database, string sql, params object[] parameters) { var reader = database.ExecuteReader(sql, parameters); return reader.FetchResultDynamic(); } /// /// Fetches the SQL json. /// /// The database. /// The SQL. /// The parameters. /// public static StoreResultModel FetchSqlJson(this DatabaseFacade database, string sql, params object[] parameters) { var reader = database.ExecuteReader(sql, parameters); return reader.FetchResultJson(); } /// /// Fetches the SQL asynchronous. /// /// /// The database. /// The cancellation token. /// The SQL. /// The parameters. /// public static async Task> FetchSqlAsync(this DatabaseFacade database, CancellationToken cancellationToken, string sql, params object[] parameters) where T : class, new() { var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false); return await FetchResultAsync(reader, cancellationToken).ConfigureAwait(false); } /// /// Fetches the SQL asynchronous. /// /// /// The database. /// The SQL. /// The parameters. /// public static async Task> FetchSqlAsync(this DatabaseFacade database, string sql, params object[] parameters) where T : class, new() { return await database.FetchSqlAsync(CancellationToken.None, sql, parameters).ConfigureAwait(false); } /// /// Fetches the SQL. /// /// The type of the result. /// The database. /// The selector. /// The SQL. /// The parameters. /// public static FuncResultList FetchSql(this DatabaseFacade database, Func selector, string sql, params object[] parameters) { var reader = database.ExecuteReader(sql, parameters); return reader.FetchResult(selector); } /// /// Fetches the SQL asynchronous. /// /// The type of the result. /// The database. /// The selector. /// The cancellation token. /// The SQL. /// The parameters. /// public static async Task> FetchSqlAsync(this DatabaseFacade database, Func selector, CancellationToken cancellationToken, string sql, params object[] parameters) { var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false); return await FetchResultAsync(reader, selector, cancellationToken).ConfigureAwait(false); } /// /// Fetches the SQL asynchronous. /// /// The type of the result. /// The database. /// The selector. /// The SQL. /// The parameters. /// public static async Task> FetchSqlAsync(this DatabaseFacade database, Func selector, string sql, params object[] parameters) { return await database.FetchSqlAsync(selector, CancellationToken.None, sql, parameters).ConfigureAwait(false); } /// /// Selects the SQL. /// /// /// The database. /// The SQL. /// The parameters. /// public static IList SelectSql(this DatabaseFacade database, string sql, params object[] parameters) where T : class, new() { var reader = database.ExecuteReader(sql, parameters); bool hasNextResult = false; reader.FetchResult()(out var list, out hasNextResult); return list; } /// /// Selects the SQL asynchronous. /// /// /// The database. /// The cancellation token. /// The SQL. /// The parameters. /// public static async Task> SelectSqlAsync(this DatabaseFacade database, CancellationToken cancellationToken, string sql, params object[] parameters) where T : class, new() { var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false); bool hasNextResult = false; (await FetchResultAsync(reader, cancellationToken).ConfigureAwait(false))(out var list, out hasNextResult); return list; } /// /// Selects the SQL asynchronous. /// /// /// The database. /// The SQL. /// The parameters. /// public static async Task> SelectSqlAsync(this DatabaseFacade database, string sql, params object[] parameters) where T : class, new() { return await database.SelectSqlAsync(CancellationToken.None, sql, parameters).ConfigureAwait(false); } /// /// Selects the SQL. /// /// The type of the result. /// The database. /// The selector. /// The SQL. /// The parameters. /// public static IList SelectSql(this DatabaseFacade database, Func selector, string sql, params object[] parameters) { var reader = database.ExecuteReader(sql, parameters); bool hasNextResult = false; reader.FetchResult(selector)(out var list, out hasNextResult); return list; } /// /// Selects the SQL asynchronous. /// /// The type of the result. /// The database. /// The cancellation token. /// The selector. /// The SQL. /// The parameters. /// public static async Task> SelectSqlAsync(this DatabaseFacade database, Func selector, CancellationToken cancellationToken, string sql, params object[] parameters) { var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false); bool hasNextResult = false; (await FetchResultAsync(reader, selector, cancellationToken).ConfigureAwait(false))(out var list, out hasNextResult); return list; } /// /// Selects the SQL asynchronous. /// /// The type of the result. /// The database. /// The selector. /// The SQL. /// The parameters. /// public static async Task> SelectSqlAsync(this DatabaseFacade database, Func selector, string sql, params object[] parameters) { return await database.SelectSqlAsync(selector, CancellationToken.None, sql, parameters).ConfigureAwait(false); } /// /// Selects the SQL to dataset and output dictionary. /// /// The database. /// The SQL. /// The parameters. /// public static StoreResultModel> SelectSqlToDataSetOutput(this DatabaseFacade database, string sql, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); var reader = database.ExecuteReader(sql, fixParams); var data = reader.FetchToDataSet(); var result = ParameterUtils.GatherOutputParameters(data.Tables.Count, fixParams); result.ForEach(p => data.ExtendedProperties[p.Key] = p.Value); return (out DataSet models) => { models = data; return result; }; } /// /// Selects the SQL to data set output asynchronous. /// /// The database. /// The cancellation token. /// The SQL. /// The parameters. /// public static async Task>> SelectSqlToDataSetOutputAsync(this DatabaseFacade database, CancellationToken cancellationToken, string sql, params object[] parameters) { var fixParams = ParameterUtils.GetParameters(false, parameters); var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false); var data = await reader.FetchToDataSetAsync(); var result = ParameterUtils.GatherOutputParameters(data.Tables.Count, fixParams); return (out DataSet models) => { models = data; return result; }; } /// /// Selects the SQL to data set asynchronous. /// /// The database. /// The SQL. /// The parameters. /// public static DataSet SelectSqlToDataSet(this DatabaseFacade database, string sql, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); var reader = database.ExecuteReader(sql, fixParams); var dataSet = reader.FetchToDataSet(); var result = ParameterUtils.GatherOutputParameters(dataSet.Tables.Count, fixParams); result.ForEach(p => dataSet.ExtendedProperties[p.Key] = p.Value); return dataSet; } /// /// Selects the SQL to data set asynchronous. /// /// The database. /// The cancellation token. /// The SQL. /// The parameters. /// public static async Task SelectSqlToDataSetAsync(this DatabaseFacade database, CancellationToken cancellationToken, string sql, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); var reader = await database.ExecuteReaderAsync(cancellationToken, sql, parameters).ConfigureAwait(false); var dataSet = await reader.FetchToDataSetAsync(); var result = ParameterUtils.GatherOutputParameters(dataSet.Tables.Count, fixParams); result.ForEach(p => dataSet.ExtendedProperties[p.Key] = p.Value); return dataSet; } /// /// Executes the store procedure. /// /// The database. /// The store procedure. /// The parameters. /// public static Dictionary ExecStoreProcedure(this DatabaseFacade database, string storeProcedure, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); int rowsAffected = database.ExecuteNonQuery(queryString, fixParams); var result = ParameterUtils.GatherOutputParameters(rowsAffected, fixParams); return result; } /// /// Executes the store procedure asynchronous. /// /// The database. /// The cancellation token. /// The store procedure. /// The parameters. /// public static async Task> ExecStoreProcedureAsync(this DatabaseFacade database, CancellationToken cancellationToken, string storeProcedure, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); int rowsAffected = await database.ExecuteNonQueryAsync(queryString, cancellationToken, fixParams).ConfigureAwait(false); var result = ParameterUtils.GatherOutputParameters(rowsAffected, fixParams); return result; } /// /// Executes the store procedure asynchronous. /// /// The database. /// The store procedure. /// The parameters. /// public static async Task> ExecStoreProcedureAsync(this DatabaseFacade database, string storeProcedure, params object[] parameters) { return await database.ExecStoreProcedureAsync(CancellationToken.None, storeProcedure, storeProcedure, parameters).ConfigureAwait(false); } /// /// Stores the procedure get data set. /// /// The database. /// The store procedure. /// The parameters. /// public static DataSet StoreProcedureGetDataSet(this DatabaseFacade database, string storeProcedure, params object[] parameters) { var fixParams = ParameterUtils.GetParameters(false, parameters); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); var reader = database.ExecuteReader(queryString, fixParams); var dataSet = reader.FetchToDataSet(parameters: fixParams); return dataSet; } /// /// Stores the procedure get. /// /// /// The database. /// The store procedure. /// The parameters. /// public static StoreResultList> StoreProcedureGet(this DatabaseFacade database, string storeProcedure, params object[] parameters) where T : class, new() { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); var list = database.SelectSql(queryString, fixParams); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models) => { models = list; return result; }; } /// /// Stores the procedure get dynamic. /// /// The database. /// The store procedure. /// The parameters. /// /// public static StoreResultList> StoreProcedureGet(this DatabaseFacade database, string storeProcedure, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); var reader = database.ExecuteReader(queryString, fixParams); var list = reader.FetchToDynamic(); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models) => { models = list; return result; }; } /// /// Stores the procedure get asynchronous. /// /// /// The database. /// The cancellation token. /// The store procedure. /// The parameters. /// public static async Task>> StoreProcedureGetAsync(this DatabaseFacade database, CancellationToken cancellationToken, string storeProcedure, params object[] parameters) where T : class, new() { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); var list = await database.SelectSqlAsync(cancellationToken, queryString, fixParams).ConfigureAwait(false); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models) => { models = list; return result; }; } /// /// Stores the procedure get asynchronous. /// /// /// The database. /// The store procedure. /// The parameters. /// public static async Task>> StoreProcedureGetAsync(this DatabaseFacade database, string storeProcedure, params object[] parameters) where T : class, new() { return await database.StoreProcedureGetAsync(CancellationToken.None, storeProcedure, parameters).ConfigureAwait(false); } /// /// Stores the procedure get. /// /// The type of the result. /// The database. /// The selector. /// The store procedure. /// The parameters. /// public static StoreResultList> StoreProcedureGet(this DatabaseFacade database, Func selector, string storeProcedure, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); var list = database.SelectSql(selector, queryString, fixParams); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models) => { models = list; return result; }; } /// /// Stores the procedure get asynchronous. /// /// The type of the result. /// The database. /// The selector. /// The cancellation token. /// The store procedure. /// The parameters. /// public static async Task>> StoreProcedureGetAsync(this DatabaseFacade database, Func selector, CancellationToken cancellationToken, string storeProcedure, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); var list = await database.SelectSqlAsync(selector, cancellationToken, queryString, fixParams).ConfigureAwait(false); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models) => { models = list; return result; }; } /// /// Stores the procedure get asynchronous. /// /// The type of the result. /// The database. /// The selector. /// The store procedure. /// The parameters. /// public static async Task>> StoreProcedureGetAsync(this DatabaseFacade database, Func selector, string storeProcedure, params object[] parameters) { return await database.StoreProcedureGetAsync(selector, storeProcedure, parameters).ConfigureAwait(false); } /// /// Fetches the store procedure. /// /// /// The database. /// The store procedure. /// The parameters. /// public static StoreResultList, RelationalDataReader> FetchStoreProcedure(this DatabaseFacade database, string storeProcedure, params object[] parameters) where T : class, new() { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); bool nextResult = false; var reader = database.FetchSql(queryString, fixParams)(out var list, out nextResult); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models, out Dictionary outVars, out bool hasNextResult) => { models = list; outVars = result; hasNextResult = nextResult; return reader; }; } /// /// Fetches the store procedure. /// /// The database. /// The store procedure. /// The parameters. /// /// public static StoreResultList, RelationalDataReader> FetchStoreProcedureDynamic(this DatabaseFacade database, string storeProcedure, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); bool nextResult = false; var reader = database.FetchSqlDynamic(queryString, fixParams)(out var list, out nextResult); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models, out Dictionary outVars, out bool hasNextResult) => { models = list; outVars = result; hasNextResult = nextResult; return reader; }; } /// /// Fetches the store procedure json. /// /// The database. /// The store procedure. /// The parameters. /// public static string FetchStoreProcedureJson(this DatabaseFacade database, string storeProcedure, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); var reader = database.FetchSqlJson(queryString, fixParams)(out string data); return data; } /// /// Fetches the store procedure asynchronous. /// /// /// The database. /// The cancellation token. /// The store procedure. /// The parameters. /// public static async Task, RelationalDataReader>> FetchStoreProcedureAsync(this DatabaseFacade database, CancellationToken cancellationToken, string storeProcedure, params object[] parameters) where T : class, new() { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); bool nextResult = false; var reader = (await database.FetchSqlAsync(cancellationToken, queryString, fixParams).ConfigureAwait(false))(out var list, out nextResult); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models, out Dictionary outVars, out bool hasNextResult) => { models = list; outVars = result; hasNextResult = nextResult; return reader; }; } /// /// Fetches the store procedure asynchronous. /// /// /// The database. /// The store procedure. /// The parameters. /// public static async Task, RelationalDataReader>> FetchStoreProcedureAsync(this DatabaseFacade database, string storeProcedure, params object[] parameters) where T : class, new() { return await database.FetchStoreProcedureAsync(CancellationToken.None, storeProcedure, parameters).ConfigureAwait(false); } /// /// Fetches the store procedure. /// /// The type of the result. /// The database. /// The selector. /// The store procedure. /// The parameters. /// public static StoreResultList, RelationalDataReader> FetchStoreProcedure(this DatabaseFacade database, Func selector, string storeProcedure, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); bool nextResult = false; var reader = database.FetchSql(selector, queryString, fixParams)(out var list, out nextResult); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models, out Dictionary outVars, out bool hasNextResult) => { models = list; outVars = result; hasNextResult = nextResult; return reader; }; } /// /// Fetches the store procedure asynchronous. /// /// The type of the result. /// The database. /// The selector. /// The cancellation token. /// The store procedure. /// The parameters. /// public static async Task, RelationalDataReader>> FetchStoreProcedureAsync(this DatabaseFacade database, Func selector, CancellationToken cancellationToken, string storeProcedure, params object[] parameters) { var fixParams = ConvertParameters(database, ParameterUtils.GetParameters(false, parameters)); string queryString = GetExecStoreProcedureString(storeProcedure, fixParams); bool nextResult = false; var reader = (await database.FetchSqlAsync(selector, cancellationToken, queryString, fixParams).ConfigureAwait(false))(out var list, out nextResult); var result = ParameterUtils.GatherOutputParameters(list.Count, fixParams); return (out IList models, out Dictionary outVars, out bool hasNextResult) => { models = list; outVars = result; hasNextResult = nextResult; return reader; }; } } }