Skip to content

Commit 5050b68

Browse files
committed
- Added method WithSqlParams that takes SqlParameter[] (issue snickler#25)
- Added method ExecuteStoredProcAsync that takes params Action<SprocResults>[] - In MapToList: replaced usage of Activator.CreateInstance in MapToList with new T() (issue snickler#5) - In MapToList: tweaked string compares to follow better practices - Formatting - Fixes to XML documentation - Finor refactoring / readability fixes - Removed unused parameters from some methods: - WithSqlParam that takes SqlParameter - removed unused paramName - ExecuteStoredNonQuery - removed unused commandBehavior - ExecuteStoredNonQueryAsync - removed unused commandBehavior
1 parent e899197 commit 5050b68

File tree

1 file changed

+132
-59
lines changed

1 file changed

+132
-59
lines changed

EFCoreFluent/src/EFCoreFluent/EFExtensions.cs

Lines changed: 132 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@ public static class EFExtensions
2424
/// <param name="prependDefaultSchema">Prepend the default schema name to <paramref name="storedProcName"/> if explicitly defined in <paramref name="context"/></param>
2525
/// <param name="commandTimeout">Command timeout in seconds. Default is 30.</param>
2626
/// <returns></returns>
27-
public static DbCommand LoadStoredProc(this DbContext context, string storedProcName, bool prependDefaultSchema = true, short commandTimeout = 30)
27+
public static DbCommand LoadStoredProc(this DbContext context, string storedProcName,
28+
bool prependDefaultSchema = true, short commandTimeout = 30)
2829
{
29-
3030
var cmd = context.Database.GetDbConnection().CreateCommand();
31-
3231
cmd.CommandTimeout = commandTimeout;
3332

3433
if (prependDefaultSchema)
@@ -56,15 +55,17 @@ public static DbCommand LoadStoredProc(this DbContext context, string storedProc
5655
/// <param name="cmd"></param>
5756
/// <param name="paramName"></param>
5857
/// <param name="paramValue"></param>
58+
/// <param name="configureParam"></param>
5959
/// <returns></returns>
60-
public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, object paramValue, Action<DbParameter> configureParam = null)
60+
public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, object paramValue,
61+
Action<DbParameter> configureParam = null)
6162
{
6263
if (string.IsNullOrEmpty(cmd.CommandText) && cmd.CommandType != System.Data.CommandType.StoredProcedure)
6364
throw new InvalidOperationException("Call LoadStoredProc before using this method");
6465

6566
var param = cmd.CreateParameter();
6667
param.ParameterName = paramName;
67-
param.Value = (paramValue != null ? paramValue : DBNull.Value);
68+
param.Value = paramValue ?? DBNull.Value;
6869
configureParam?.Invoke(param);
6970
cmd.Parameters.Add(param);
7071
return cmd;
@@ -75,9 +76,10 @@ public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, objec
7576
/// </summary>
7677
/// <param name="cmd"></param>
7778
/// <param name="paramName"></param>
78-
/// <param name="paramValue"></param>
79+
/// <param name="configureParam"></param>
7980
/// <returns></returns>
80-
public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, Action<DbParameter> configureParam = null)
81+
public static DbCommand WithSqlParam(this DbCommand cmd, string paramName,
82+
Action<DbParameter> configureParam = null)
8183
{
8284
if (string.IsNullOrEmpty(cmd.CommandText) && cmd.CommandType != System.Data.CommandType.StoredProcedure)
8385
throw new InvalidOperationException("Call LoadStoredProc before using this method");
@@ -90,14 +92,13 @@ public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, Actio
9092
}
9193

9294
/// <summary>
93-
/// Creates a DbParameter object based on the SqlParameter and adds it to a DbCommand.
95+
/// Adds a SqlParameter to a DbCommand.
9496
/// This enabled the ability to provide custom types for SQL-parameters.
9597
/// </summary>
9698
/// <param name="cmd"></param>
97-
/// <param name="paramName"></param>
98-
/// <param name="paramValue"></param>
99+
/// <param name="parameter"></param>
99100
/// <returns></returns>
100-
public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, SqlParameter parameter)
101+
public static DbCommand WithSqlParam(this DbCommand cmd, SqlParameter parameter)
101102
{
102103
if (string.IsNullOrEmpty(cmd.CommandText) && cmd.CommandType != System.Data.CommandType.StoredProcedure)
103104
throw new InvalidOperationException("Call LoadStoredProc before using this method");
@@ -107,17 +108,33 @@ public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, SqlPa
107108
return cmd;
108109
}
109110

110-
public class SprocResults
111+
/// <summary>
112+
/// Adds an array of SqlParameters to a DbCommand
113+
/// </summary>
114+
/// <param name="cmd"></param>
115+
/// <param name="parameters"></param>
116+
/// <returns></returns>
117+
/// <exception cref="InvalidOperationException"></exception>
118+
public static DbCommand WithSqlParams(this DbCommand cmd, SqlParameter[] parameters)
111119
{
120+
if (string.IsNullOrEmpty(cmd.CommandText) && cmd.CommandType != System.Data.CommandType.StoredProcedure)
121+
throw new InvalidOperationException("Call LoadStoredProc before using this method");
112122

113-
private DbDataReader _reader;
123+
cmd.Parameters.AddRange(parameters);
124+
125+
return cmd;
126+
}
127+
128+
public class SprocResults
129+
{
130+
private readonly DbDataReader _reader;
114131

115132
public SprocResults(DbDataReader reader)
116133
{
117134
_reader = reader;
118135
}
119136

120-
public IList<T> ReadToList<T>()
137+
public IList<T> ReadToList<T>() where T : new()
121138
{
122139
return MapToList<T>(_reader);
123140
}
@@ -147,64 +164,73 @@ public bool NextResult()
147164
/// </summary>
148165
/// <typeparam name="T"></typeparam>
149166
/// <param name="dr"></param>
150-
/// <returns>IList<<typeparamref name="T"/>></returns>
151-
private IList<T> MapToList<T>(DbDataReader dr)
167+
/// <returns>IList&lt;<typeparam name="T">&gt;</typeparam></returns>
168+
private static IList<T> MapToList<T>(DbDataReader dr) where T : new()
152169
{
153170
var objList = new List<T>();
154171
var props = typeof(T).GetRuntimeProperties().ToList();
155172

156173
var colMapping = dr.GetColumnSchema()
157-
.Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
158-
.ToDictionary(key => key.ColumnName.ToLower());
174+
.Where(x => props.Any(y =>
175+
string.Equals(y.Name, x.ColumnName, StringComparison.CurrentCultureIgnoreCase)))
176+
.ToDictionary(key => key.ColumnName.ToUpper());
159177

160-
if (dr.HasRows)
178+
if (!dr.HasRows)
179+
return objList;
180+
181+
while (dr.Read())
161182
{
162-
while (dr.Read())
183+
var obj = new T();
184+
foreach (var prop in props)
163185
{
164-
T obj = Activator.CreateInstance<T>();
165-
foreach (var prop in props)
166-
{
167-
if (colMapping.ContainsKey(prop.Name.ToLower()))
168-
{
169-
var column = colMapping[prop.Name.ToLower()];
170-
171-
if (column?.ColumnOrdinal != null)
172-
{
173-
var val = dr.GetValue(column.ColumnOrdinal.Value);
174-
prop.SetValue(obj, val == DBNull.Value ? null : val);
175-
}
176-
177-
}
178-
}
179-
objList.Add(obj);
186+
var upperName = prop.Name.ToUpper();
187+
188+
if (!colMapping.ContainsKey(upperName))
189+
continue;
190+
191+
var column = colMapping[upperName];
192+
193+
if (column?.ColumnOrdinal == null)
194+
continue;
195+
196+
var val = dr.GetValue(column.ColumnOrdinal.Value);
197+
prop.SetValue(obj, val == DBNull.Value ? null : val);
180198
}
199+
200+
objList.Add(obj);
181201
}
202+
182203
return objList;
183204
}
184205

185206
/// <summary>
186-
///Attempts to read the first value of the first row of the resultset.
207+
/// Attempts to read the first value of the first row of the result set.
187208
/// </summary>
188-
private T? MapToValue<T>(DbDataReader dr) where T : struct
209+
private static T? MapToValue<T>(DbDataReader dr) where T : struct
189210
{
190-
if (dr.HasRows)
211+
if (!dr.HasRows)
212+
return new T?();
213+
214+
if (dr.Read())
191215
{
192-
if (dr.Read())
193-
{
194-
return dr.IsDBNull(0) ? new T?() : new T?(dr.GetFieldValue<T>(0));
195-
}
216+
return dr.IsDBNull(0) ? new T?() : dr.GetFieldValue<T>(0);
196217
}
218+
197219
return new T?();
198220
}
199221
}
200222

201223
/// <summary>
202-
/// Executes a DbDataReader and returns a list of mapped column values to the properties of <typeparamref name="T"/>
224+
/// Executes a DbDataReader and passes the results to <paramref name="handleResults"/>
203225
/// </summary>
204-
/// <typeparam name="T"></typeparam>
205226
/// <param name="command"></param>
227+
/// <param name="handleResults"></param>
228+
/// <param name="commandBehaviour"></param>
229+
/// <param name="manageConnection"></param>
206230
/// <returns></returns>
207-
public static void ExecuteStoredProc(this DbCommand command, Action<SprocResults> handleResults, System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, bool manageConnection = true)
231+
public static void ExecuteStoredProc(this DbCommand command, Action<SprocResults> handleResults,
232+
System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default,
233+
bool manageConnection = true)
208234
{
209235
if (handleResults == null)
210236
{
@@ -234,12 +260,17 @@ public static void ExecuteStoredProc(this DbCommand command, Action<SprocResults
234260
}
235261

236262
/// <summary>
237-
/// Executes a DbDataReader asynchronously and returns a list of mapped column values to the properties of <typeparamref name="T"/>.
263+
/// Executes a DbDataReader asynchronously and passes the results to <paramref name="handleResults"/>
238264
/// </summary>
239-
/// <typeparam name="T"></typeparam>
240265
/// <param name="command"></param>
266+
/// <param name="handleResults"></param>
267+
/// <param name="commandBehaviour"></param>
268+
/// <param name="ct"></param>
269+
/// <param name="manageConnection"></param>
241270
/// <returns></returns>
242-
public async static Task ExecuteStoredProcAsync(this DbCommand command, Action<SprocResults> handleResults, System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, CancellationToken ct = default(CancellationToken), bool manageConnection = true)
271+
public static async Task ExecuteStoredProcAsync(this DbCommand command, Action<SprocResults> handleResults,
272+
System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default,
273+
CancellationToken ct = default, bool manageConnection = true)
243274
{
244275
if (handleResults == null)
245276
{
@@ -252,7 +283,8 @@ public static void ExecuteStoredProc(this DbCommand command, Action<SprocResults
252283
await command.Connection.OpenAsync(ct).ConfigureAwait(false);
253284
try
254285
{
255-
using (var reader = await command.ExecuteReaderAsync(commandBehaviour, ct).ConfigureAwait(false))
286+
using (var reader = await command.ExecuteReaderAsync(commandBehaviour, ct)
287+
.ConfigureAwait(false))
256288
{
257289
var sprocResults = new SprocResults(reader);
258290
handleResults(sprocResults);
@@ -269,15 +301,57 @@ public static void ExecuteStoredProc(this DbCommand command, Action<SprocResults
269301
}
270302

271303
/// <summary>
272-
/// Executes a non-query.
304+
/// Executes a DbDataReader asynchronously and passes the results thru all <paramref name="resultActions"/>
273305
/// </summary>
274306
/// <param name="command"></param>
275307
/// <param name="commandBehaviour"></param>
308+
/// <param name="ct"></param>
309+
/// <param name="manageConnection"></param>
310+
/// <param name="resultActions"></param>
311+
/// <returns></returns>
312+
public static async Task ExecuteStoredProcAsync(this DbCommand command,
313+
System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default,
314+
CancellationToken ct = default, bool manageConnection = true, params Action<SprocResults>[] resultActions)
315+
{
316+
if (resultActions == null)
317+
{
318+
throw new ArgumentNullException(nameof(resultActions));
319+
}
320+
321+
using (command)
322+
{
323+
if (manageConnection && command.Connection.State == System.Data.ConnectionState.Closed)
324+
await command.Connection.OpenAsync(ct).ConfigureAwait(false);
325+
try
326+
{
327+
using (var reader = await command.ExecuteReaderAsync(commandBehaviour, ct)
328+
.ConfigureAwait(false))
329+
{
330+
var sprocResults = new SprocResults(reader);
331+
332+
foreach (var t in resultActions)
333+
t(sprocResults);
334+
}
335+
}
336+
finally
337+
{
338+
if (manageConnection)
339+
{
340+
command.Connection.Close();
341+
}
342+
}
343+
}
344+
}
345+
346+
/// <summary>
347+
/// Executes a non-query.
348+
/// </summary>
349+
/// <param name="command"></param>
276350
/// <param name="manageConnection"></param>
277351
/// <returns></returns>
278-
public static int ExecuteStoredNonQuery(this DbCommand command, System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, bool manageConnection = true)
352+
public static int ExecuteStoredNonQuery(this DbCommand command, bool manageConnection = true)
279353
{
280-
int numberOfRecordsAffected = -1;
354+
var numberOfRecordsAffected = -1;
281355

282356
using (command)
283357
{
@@ -306,13 +380,13 @@ public static int ExecuteStoredNonQuery(this DbCommand command, System.Data.Comm
306380
/// Executes a non-query asynchronously.
307381
/// </summary>
308382
/// <param name="command"></param>
309-
/// <param name="commandBehaviour"></param>
310383
/// <param name="ct"></param>
311384
/// <param name="manageConnection"></param>
312385
/// <returns></returns>
313-
public async static Task<int> ExecuteStoredNonQueryAsync(this DbCommand command, System.Data.CommandBehavior commandBehaviour = System.Data.CommandBehavior.Default, CancellationToken ct = default(CancellationToken), bool manageConnection = true)
386+
public static async Task<int> ExecuteStoredNonQueryAsync(this DbCommand command, CancellationToken ct = default,
387+
bool manageConnection = true)
314388
{
315-
int numberOfRecordsAffected = -1;
389+
var numberOfRecordsAffected = -1;
316390

317391
using (command)
318392
{
@@ -323,7 +397,7 @@ public static int ExecuteStoredNonQuery(this DbCommand command, System.Data.Comm
323397

324398
try
325399
{
326-
numberOfRecordsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false);
400+
numberOfRecordsAffected = await command.ExecuteNonQueryAsync(ct).ConfigureAwait(false);
327401
}
328402
finally
329403
{
@@ -336,6 +410,5 @@ public static int ExecuteStoredNonQuery(this DbCommand command, System.Data.Comm
336410

337411
return numberOfRecordsAffected;
338412
}
339-
340413
}
341-
}
414+
}

0 commit comments

Comments
 (0)