diff --git a/EFCoreFluent/src/EFCoreFluent/EFExtensions.cs b/EFCoreFluent/src/EFCoreFluent/EFExtensions.cs index ef1355c..102003c 100644 --- a/EFCoreFluent/src/EFCoreFluent/EFExtensions.cs +++ b/EFCoreFluent/src/EFCoreFluent/EFExtensions.cs @@ -24,11 +24,10 @@ public static class EFExtensions /// Prepend the default schema name to if explicitly defined in /// Command timeout in seconds. Default is 30. /// - public static DbCommand LoadStoredProc(this DbContext context, string storedProcName, bool prependDefaultSchema = true, short commandTimeout = 30) + public static DbCommand LoadStoredProc(this DbContext context, string storedProcName, + bool prependDefaultSchema = true, short commandTimeout = 30) { - var cmd = context.Database.GetDbConnection().CreateCommand(); - cmd.CommandTimeout = commandTimeout; if (prependDefaultSchema) @@ -56,15 +55,17 @@ public static DbCommand LoadStoredProc(this DbContext context, string storedProc /// /// /// + /// /// - public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, object paramValue, Action configureParam = null) + public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, object paramValue, + Action configureParam = null) { if (string.IsNullOrEmpty(cmd.CommandText) && cmd.CommandType != System.Data.CommandType.StoredProcedure) throw new InvalidOperationException("Call LoadStoredProc before using this method"); var param = cmd.CreateParameter(); param.ParameterName = paramName; - param.Value = (paramValue != null ? paramValue : DBNull.Value); + param.Value = paramValue ?? DBNull.Value; configureParam?.Invoke(param); cmd.Parameters.Add(param); return cmd; @@ -75,9 +76,10 @@ public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, objec /// /// /// - /// + /// /// - public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, Action configureParam = null) + public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, + Action configureParam = null) { if (string.IsNullOrEmpty(cmd.CommandText) && cmd.CommandType != System.Data.CommandType.StoredProcedure) throw new InvalidOperationException("Call LoadStoredProc before using this method"); @@ -90,14 +92,13 @@ public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, Actio } /// - /// Creates a DbParameter object based on the SqlParameter and adds it to a DbCommand. + /// Adds a SqlParameter to a DbCommand. /// This enabled the ability to provide custom types for SQL-parameters. /// /// - /// - /// + /// /// - public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, SqlParameter parameter) + public static DbCommand WithSqlParam(this DbCommand cmd, SqlParameter parameter) { if (string.IsNullOrEmpty(cmd.CommandText) && cmd.CommandType != System.Data.CommandType.StoredProcedure) throw new InvalidOperationException("Call LoadStoredProc before using this method"); @@ -107,17 +108,33 @@ public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, SqlPa return cmd; } - public class SprocResults + /// + /// Adds an array of SqlParameters to a DbCommand + /// + /// + /// + /// + /// + public static DbCommand WithSqlParams(this DbCommand cmd, SqlParameter[] parameters) { + if (string.IsNullOrEmpty(cmd.CommandText) && cmd.CommandType != System.Data.CommandType.StoredProcedure) + throw new InvalidOperationException("Call LoadStoredProc before using this method"); - private DbDataReader _reader; + cmd.Parameters.AddRange(parameters); + + return cmd; + } + + public class SprocResults + { + private readonly DbDataReader _reader; public SprocResults(DbDataReader reader) { _reader = reader; } - public IList ReadToList() + public IList ReadToList() where T : new() { return MapToList(_reader); } @@ -147,64 +164,73 @@ public bool NextResult() /// /// /// - /// IList<> - private IList MapToList(DbDataReader dr) + /// IList<> + private static IList MapToList(DbDataReader dr) where T : new() { var objList = new List(); var props = typeof(T).GetRuntimeProperties().ToList(); var colMapping = dr.GetColumnSchema() - .Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower())) - .ToDictionary(key => key.ColumnName.ToLower()); + .Where(x => props.Any(y => + string.Equals(y.Name, x.ColumnName, StringComparison.CurrentCultureIgnoreCase))) + .ToDictionary(key => key.ColumnName.ToUpper()); - if (dr.HasRows) + if (!dr.HasRows) + return objList; + + while (dr.Read()) { - while (dr.Read()) + var obj = new T(); + foreach (var prop in props) { - T obj = Activator.CreateInstance(); - foreach (var prop in props) - { - if (colMapping.ContainsKey(prop.Name.ToLower())) - { - var column = colMapping[prop.Name.ToLower()]; - - if (column?.ColumnOrdinal != null) - { - var val = dr.GetValue(column.ColumnOrdinal.Value); - prop.SetValue(obj, val == DBNull.Value ? null : val); - } - - } - } - objList.Add(obj); + var upperName = prop.Name.ToUpper(); + + if (!colMapping.ContainsKey(upperName)) + continue; + + var column = colMapping[upperName]; + + if (column?.ColumnOrdinal == null) + continue; + + var val = dr.GetValue(column.ColumnOrdinal.Value); + prop.SetValue(obj, val == DBNull.Value ? null : val); } + + objList.Add(obj); } + return objList; } /// - ///Attempts to read the first value of the first row of the resultset. + /// Attempts to read the first value of the first row of the result set. /// - private T? MapToValue(DbDataReader dr) where T : struct + private static T? MapToValue(DbDataReader dr) where T : struct { - if (dr.HasRows) + if (!dr.HasRows) + return new T?(); + + if (dr.Read()) { - if (dr.Read()) - { - return dr.IsDBNull(0) ? new T?() : new T?(dr.GetFieldValue(0)); - } + return dr.IsDBNull(0) ? new T?() : dr.GetFieldValue(0); } + return new T?(); } } /// - /// Executes a DbDataReader and returns a list of mapped column values to the properties of + /// Executes a DbDataReader and passes the results to /// - /// /// + /// + /// + /// /// - public static void ExecuteStoredProc(this DbCommand command, Action handleResults, System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, bool manageConnection = true) + public static void ExecuteStoredProc(this DbCommand command, Action handleResults, + System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, + bool manageConnection = true) { if (handleResults == null) { @@ -234,12 +260,17 @@ public static void ExecuteStoredProc(this DbCommand command, Action - /// Executes a DbDataReader asynchronously and returns a list of mapped column values to the properties of . + /// Executes a DbDataReader asynchronously and passes the results to /// - /// /// + /// + /// + /// + /// /// - public async static Task ExecuteStoredProcAsync(this DbCommand command, Action handleResults, System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, CancellationToken ct = default(CancellationToken), bool manageConnection = true) + public static async Task ExecuteStoredProcAsync(this DbCommand command, Action handleResults, + System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, + CancellationToken ct = default, bool manageConnection = true) { if (handleResults == null) { @@ -252,7 +283,8 @@ public static void ExecuteStoredProc(this DbCommand command, Action - /// Executes a non-query. + /// Executes a DbDataReader asynchronously and passes the results thru all /// /// /// + /// + /// + /// + /// + public static async Task ExecuteStoredProcAsync(this DbCommand command, + System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, + CancellationToken ct = default, bool manageConnection = true, params Action[] resultActions) + { + if (resultActions == null) + { + throw new ArgumentNullException(nameof(resultActions)); + } + + using (command) + { + if (manageConnection && command.Connection.State == System.Data.ConnectionState.Closed) + await command.Connection.OpenAsync(ct).ConfigureAwait(false); + try + { + using (var reader = await command.ExecuteReaderAsync(commandBehaviour, ct) + .ConfigureAwait(false)) + { + var sprocResults = new SprocResults(reader); + + foreach (var t in resultActions) + t(sprocResults); + } + } + finally + { + if (manageConnection) + { + command.Connection.Close(); + } + } + } + } + + /// + /// Executes a non-query. + /// + /// /// /// - public static int ExecuteStoredNonQuery(this DbCommand command, System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, bool manageConnection = true) + public static int ExecuteStoredNonQuery(this DbCommand command, bool manageConnection = true) { - int numberOfRecordsAffected = -1; + var numberOfRecordsAffected = -1; using (command) { @@ -306,13 +380,13 @@ public static int ExecuteStoredNonQuery(this DbCommand command, System.Data.Comm /// Executes a non-query asynchronously. /// /// - /// /// /// /// - public async static Task ExecuteStoredNonQueryAsync(this DbCommand command, System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, CancellationToken ct = default(CancellationToken), bool manageConnection = true) + public static async Task ExecuteStoredNonQueryAsync(this DbCommand command, CancellationToken ct = default, + bool manageConnection = true) { - int numberOfRecordsAffected = -1; + var numberOfRecordsAffected = -1; using (command) { @@ -323,7 +397,7 @@ public static int ExecuteStoredNonQuery(this DbCommand command, System.Data.Comm try { - numberOfRecordsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + numberOfRecordsAffected = await command.ExecuteNonQueryAsync(ct).ConfigureAwait(false); } finally { @@ -336,6 +410,5 @@ public static int ExecuteStoredNonQuery(this DbCommand command, System.Data.Comm return numberOfRecordsAffected; } - } -} +} \ No newline at end of file