Skip to content

Commit b738fc3

Browse files
Merge pull request #564 from johelvisguzman/issue561
Simplified ado.net context mapper
2 parents 4d901de + 8fea668 commit b738fc3

File tree

8 files changed

+378
-391
lines changed

8 files changed

+378
-391
lines changed

src/DotNetToolkit.Repository.AdoNet/DbHelper.cs

Lines changed: 8 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -428,37 +428,18 @@ public T ExecuteObject<T>(string cmdText, Dictionary<string, object> parameters,
428428
/// <param name="parameters">The command parameters.</param>
429429
/// <param name="projector">A function to project each entity into a new form.</param>
430430
/// <returns>A list which each entity has been projected into a new form.</returns>
431-
internal IPagedQueryResult<IEnumerable<T>> ExecuteList<T>(string cmdText, CommandType cmdType, Dictionary<string, object> parameters, Func<DbDataReader, T> projector)
431+
internal IEnumerable<T> ExecuteList<T>(string cmdText, CommandType cmdType, Dictionary<string, object> parameters, Func<DbDataReader, T> projector)
432432
{
433433
using (var reader = ExecuteReader(cmdText, cmdType, parameters))
434434
{
435435
var list = new List<T>();
436-
var foundCrossJoinCountColumn = false;
437-
var total = 0;
438-
439-
QueryBuilder.ExtractCrossJoinColumnName(cmdText, out var crossJoinColumnName);
440436

441437
while (reader.Read())
442438
{
443-
for (var i = 0; i < reader.FieldCount; i++)
444-
{
445-
var name = reader.GetName(i);
446-
447-
if (!string.IsNullOrEmpty(crossJoinColumnName) && name.Equals(crossJoinColumnName))
448-
{
449-
total = (int)reader[name];
450-
foundCrossJoinCountColumn = true;
451-
break;
452-
}
453-
}
454-
455439
list.Add(projector(reader));
456440
}
457441

458-
if (!foundCrossJoinCountColumn)
459-
total = list.Count;
460-
461-
return new PagedQueryResult<IEnumerable<T>>(list, total);
442+
return list;
462443
}
463444
}
464445

@@ -470,25 +451,11 @@ internal IPagedQueryResult<IEnumerable<T>> ExecuteList<T>(string cmdText, Comman
470451
/// <param name="parameters">The command parameters.</param>
471452
/// <param name="projector">A function to project each entity into a new form.</param>
472453
/// <returns>A list which each entity has been projected into a new form.</returns>
473-
internal IPagedQueryResult<IEnumerable<T>> ExecuteList<T>(string cmdText, Dictionary<string, object> parameters, Func<DbDataReader, T> projector)
454+
internal IEnumerable<T> ExecuteList<T>(string cmdText, Dictionary<string, object> parameters, Func<DbDataReader, T> projector)
474455
{
475456
return ExecuteList<T>(cmdText, CommandType.Text, parameters, projector);
476457
}
477458

478-
/// <summary>
479-
/// Executes the query, and returns a list which each entity has been projected into a new form.
480-
/// </summary>
481-
/// <typeparam name="T">The type of the result set returned by the query.</typeparam>
482-
/// <param name="cmdText">The command text.</param>
483-
/// <param name="parameters">The command parameters.</param>
484-
/// <returns>A list which each entity has been projected into a new form.</returns>
485-
internal IPagedQueryResult<IEnumerable<T>> ExecuteList<T>(string cmdText, Dictionary<string, object> parameters) where T : class
486-
{
487-
var mapper = new Mapper<T>(_conventions);
488-
489-
return ExecuteList<T>(cmdText, parameters, mapper.Map);
490-
}
491-
492459
/// <summary>
493460
/// Executes the query, and returns a list which each entity has been projected into a new form.
494461
/// </summary>
@@ -497,7 +464,7 @@ internal IPagedQueryResult<IEnumerable<T>> ExecuteList<T>(string cmdText, Dictio
497464
/// <param name="cmdType">The command type.</param>
498465
/// <param name="projector">A function to project each entity into a new form.</param>
499466
/// <returns>A list which each entity has been projected into a new form.</returns>
500-
internal IPagedQueryResult<IEnumerable<T>> ExecuteList<T>(string cmdText, CommandType cmdType, Func<DbDataReader, T> projector)
467+
internal IEnumerable<T> ExecuteList<T>(string cmdText, CommandType cmdType, Func<DbDataReader, T> projector)
501468
{
502469
return ExecuteList<T>(cmdText, cmdType, null, projector);
503470
}
@@ -960,37 +927,18 @@ public DataSet ExecuteDataSet(string cmdText, Dictionary<string, object> paramet
960927
/// <param name="projector">A function to project each entity into a new form.</param>
961928
/// <param name="cancellationToken">A <see cref="System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
962929
/// <returns>The <see cref="System.Threading.Tasks.Task" /> that represents the asynchronous operation, containing a list which each entity has been projected into a new form.</returns>
963-
internal async Task<IPagedQueryResult<IEnumerable<T>>> ExecuteListAsync<T>(string cmdText, CommandType cmdType, Dictionary<string, object> parameters, Func<DbDataReader, T> projector, CancellationToken cancellationToken = new CancellationToken())
930+
internal async Task<IEnumerable<T>> ExecuteListAsync<T>(string cmdText, CommandType cmdType, Dictionary<string, object> parameters, Func<DbDataReader, T> projector, CancellationToken cancellationToken = new CancellationToken())
964931
{
965932
using (var reader = await ExecuteReaderAsync(cmdText, cmdType, parameters, cancellationToken))
966933
{
967934
var list = new List<T>();
968-
var foundCrossJoinCountColumn = false;
969-
var total = 0;
970-
971-
QueryBuilder.ExtractCrossJoinColumnName(cmdText, out var crossJoinColumnName);
972935

973-
while (reader.Read())
936+
while (await reader.ReadAsync(cancellationToken))
974937
{
975-
for (var i = 0; i < reader.FieldCount; i++)
976-
{
977-
var name = reader.GetName(i);
978-
979-
if (!string.IsNullOrEmpty(crossJoinColumnName) && name.Equals(crossJoinColumnName))
980-
{
981-
total = (int)reader[name];
982-
foundCrossJoinCountColumn = true;
983-
break;
984-
}
985-
}
986-
987938
list.Add(projector(reader));
988939
}
989940

990-
if (!foundCrossJoinCountColumn)
991-
total = list.Count;
992-
993-
return new PagedQueryResult<IEnumerable<T>>(list, total);
941+
return list;
994942
}
995943
}
996944

@@ -1003,26 +951,11 @@ public DataSet ExecuteDataSet(string cmdText, Dictionary<string, object> paramet
1003951
/// <param name="projector">A function to project each entity into a new form.</param>
1004952
/// <param name="cancellationToken">A <see cref="System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
1005953
/// <returns>The <see cref="System.Threading.Tasks.Task" /> that represents the asynchronous operation, containing a list which each entity has been projected into a new form.</returns>
1006-
internal Task<IPagedQueryResult<IEnumerable<T>>> ExecuteListAsync<T>(string cmdText, Dictionary<string, object> parameters, Func<DbDataReader, T> projector, CancellationToken cancellationToken = new CancellationToken())
954+
internal Task<IEnumerable<T>> ExecuteListAsync<T>(string cmdText, Dictionary<string, object> parameters, Func<DbDataReader, T> projector, CancellationToken cancellationToken = new CancellationToken())
1007955
{
1008956
return ExecuteListAsync<T>(cmdText, CommandType.Text, parameters, projector, cancellationToken);
1009957
}
1010958

1011-
/// <summary>
1012-
/// Asynchronously executes the query, and returns a list which each entity has been projected into a new form.
1013-
/// </summary>
1014-
/// <typeparam name="T">The type of the result set returned by the query.</typeparam>
1015-
/// <param name="cmdText">The command text.</param>
1016-
/// <param name="parameters">The command parameters.</param>
1017-
/// <param name="cancellationToken">A <see cref="System.Threading.CancellationToken" /> to observe while waiting for the task to complete.</param>
1018-
/// <returns>The <see cref="System.Threading.Tasks.Task" /> that represents the asynchronous operation, containing a list which each entity has been projected into a new form.</returns>
1019-
internal Task<IPagedQueryResult<IEnumerable<T>>> ExecuteListAsync<T>(string cmdText, Dictionary<string, object> parameters, CancellationToken cancellationToken = new CancellationToken()) where T : class
1020-
{
1021-
var mapper = new Mapper<T>(_conventions);
1022-
1023-
return ExecuteListAsync<T>(cmdText, parameters, mapper.Map, cancellationToken);
1024-
}
1025-
1026959
/// <summary>
1027960
/// Asynchronously executes the query, and returns a new <see cref="Dictionary{TDictionaryKey, TElement}" /> according to the specified <paramref name="keyProjector" />, and <paramref name="elementProjector" />.
1028961
/// </summary>

src/DotNetToolkit.Repository.AdoNet/Internal/AdoNetRepositoryContext.cs

Lines changed: 86 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -395,14 +395,13 @@ public TEntity Find<TEntity>(IFetchQueryStrategy<TEntity> fetchStrategy, params
395395
fetchStrategy != null,
396396
out var sql,
397397
out var parameters,
398-
out var navigationProperties,
399-
out var getPropertyFromColumnAliasCallback);
398+
out var mappingProperties);
400399

401-
var mapper = new Mapper<TEntity>(Conventions, navigationProperties, getPropertyFromColumnAliasCallback);
400+
var mapper = new Mapper<TEntity>(Conventions, mappingProperties);
402401

403402
ExecuteSchemaValidate(typeof(TEntity));
404403

405-
return _dbHelper.ExecuteObject<TEntity>(sql, parameters, r => mapper.Map<TEntity>(r, selectorFunc));
404+
return _dbHelper.ExecuteObject<TEntity>(sql, parameters, r => selectorFunc(mapper.Map(r)));
406405
}
407406

408407
/// <summary>
@@ -424,14 +423,13 @@ public TResult Find<TEntity, TResult>(IQueryOptions<TEntity> options, Expression
424423
options,
425424
out var sql,
426425
out var parameters,
427-
out var navigationProperties,
428-
out var getPropertyFromColumnAliasCallback);
426+
out var mappingProperties);
429427

430-
var mapper = new Mapper<TEntity>(Conventions, navigationProperties, getPropertyFromColumnAliasCallback);
428+
var mapper = new Mapper<TEntity>(Conventions, mappingProperties);
431429

432430
ExecuteSchemaValidate(typeof(TEntity));
433431

434-
return _dbHelper.ExecuteObject<TResult>(sql, parameters, r => mapper.Map<TResult>(r, selectorFunc));
432+
return _dbHelper.ExecuteObject<TResult>(sql, parameters, r => selectorFunc(mapper.Map(r)));
435433
}
436434

437435
/// <summary>
@@ -453,14 +451,42 @@ public IPagedQueryResult<IEnumerable<TResult>> FindAll<TEntity, TResult>(IQueryO
453451
options,
454452
out var sql,
455453
out var parameters,
456-
out var navigationProperties,
457-
out var getPropertyFromColumnAliasCallback);
454+
out var mappingProperties);
458455

459-
var mapper = new Mapper<TEntity>(Conventions, navigationProperties, getPropertyFromColumnAliasCallback);
456+
var mapper = new Mapper<TEntity>(Conventions, mappingProperties);
460457

461458
ExecuteSchemaValidate(typeof(TEntity));
462459

463-
return _dbHelper.ExecuteList<TResult>(sql, parameters, r => mapper.Map<TResult>(r, selectorFunc));
460+
using (var reader = _dbHelper.ExecuteReader(sql, parameters))
461+
{
462+
var list = new List<TResult>();
463+
var foundCrossJoinCountColumn = false;
464+
var total = 0;
465+
466+
QueryBuilder.ExtractCrossJoinColumnName(sql, out var crossJoinColumnName);
467+
468+
while (reader.Read())
469+
{
470+
for (var i = 0; i < reader.FieldCount; i++)
471+
{
472+
var name = reader.GetName(i);
473+
474+
if (!string.IsNullOrEmpty(crossJoinColumnName) && name.Equals(crossJoinColumnName))
475+
{
476+
total = (int)reader[name];
477+
foundCrossJoinCountColumn = true;
478+
break;
479+
}
480+
}
481+
482+
list.Add(selectorFunc(mapper.Map(reader)));
483+
}
484+
485+
if (!foundCrossJoinCountColumn)
486+
total = list.Count;
487+
488+
return new PagedQueryResult<IEnumerable<TResult>>(list, total);
489+
}
464490
}
465491

466492
/// <summary>
@@ -530,10 +556,9 @@ public IPagedQueryResult<Dictionary<TDictionaryKey, TElement>> ToDictionary<TEnt
530556
options,
531557
out var sql,
532558
out var parameters,
533-
out var navigationProperties,
534-
out var getPropertyFromColumnAliasCallback);
559+
out var mappingProperties);
535560

536-
var mapper = new Mapper<TEntity>(Conventions, navigationProperties, getPropertyFromColumnAliasCallback);
561+
var mapper = new Mapper<TEntity>(Conventions, mappingProperties);
537562

538563
ExecuteSchemaValidate(typeof(TEntity));
539564

@@ -559,7 +584,9 @@ public IPagedQueryResult<Dictionary<TDictionaryKey, TElement>> ToDictionary<TEnt
559584
}
560585
}
561586

562-
dict.Add(mapper.Map<TDictionaryKey>(reader, keySelectFunc), mapper.Map<TElement>(reader, elementSelectorFunc));
587+
var mapped = mapper.Map(reader);
588+
589+
dict.Add(keySelectFunc(mapped), elementSelectorFunc(mapped));
563590
}
564591

565592
if (!foundCrossJoinCountColumn)
@@ -740,14 +767,13 @@ public async Task<TEntity> FindAsync<TEntity>(CancellationToken cancellationToke
740767
fetchStrategy != null,
741768
out var sql,
742769
out var parameters,
743-
out var navigationProperties,
744-
out var getPropertyFromColumnAliasCallback);
770+
out var mappingProperties);
745771

746-
var mapper = new Mapper<TEntity>(Conventions, navigationProperties, getPropertyFromColumnAliasCallback);
772+
var mapper = new Mapper<TEntity>(Conventions, mappingProperties);
747773

748774
await ExecuteSchemaValidateAsync(typeof(TEntity), cancellationToken);
749775

750-
return await _dbHelper.ExecuteObjectAsync<TEntity>(sql, parameters, r => mapper.Map<TEntity>(r, selectorFunc), cancellationToken);
776+
return await _dbHelper.ExecuteObjectAsync<TEntity>(sql, parameters, r => selectorFunc(mapper.Map(r)), cancellationToken);
751777
}
752778

753779
/// <summary>
@@ -770,14 +796,13 @@ public async Task<TEntity> FindAsync<TEntity>(CancellationToken cancellationToke
770796
options,
771797
out var sql,
772798
out var parameters,
773-
out var navigationProperties,
774-
out var getPropertyFromColumnAliasCallback);
799+
out var mappingProperties);
775800

776-
var mapper = new Mapper<TEntity>(Conventions, navigationProperties, getPropertyFromColumnAliasCallback);
801+
var mapper = new Mapper<TEntity>(Conventions, mappingProperties);
777802

778803
await ExecuteSchemaValidateAsync(typeof(TEntity), cancellationToken);
779804

780-
return await _dbHelper.ExecuteObjectAsync<TResult>(sql, parameters, r => mapper.Map<TResult>(r, selectorFunc), cancellationToken);
805+
return await _dbHelper.ExecuteObjectAsync<TResult>(sql, parameters, r => selectorFunc(mapper.Map(r)), cancellationToken);
781806
}
782807

783808
/// <summary>
@@ -800,14 +825,42 @@ public async Task<TEntity> FindAsync<TEntity>(CancellationToken cancellationToke
800825
options,
801826
out var sql,
802827
out var parameters,
803-
out var navigationProperties,
804-
out var getPropertyFromColumnAliasCallback);
828+
out var mappingProperties);
805829

806-
var mapper = new Mapper<TEntity>(Conventions, navigationProperties, getPropertyFromColumnAliasCallback);
830+
var mapper = new Mapper<TEntity>(Conventions, mappingProperties);
807831

808832
await ExecuteSchemaValidateAsync(typeof(TEntity), cancellationToken);
809833

810-
return await _dbHelper.ExecuteListAsync<TResult>(sql, parameters, r => mapper.Map<TResult>(r, selectorFunc), cancellationToken);
834+
using (var reader = await _dbHelper.ExecuteReaderAsync(sql, parameters, cancellationToken))
835+
{
836+
var list = new List<TResult>();
837+
var foundCrossJoinCountColumn = false;
838+
var total = 0;
839+
840+
QueryBuilder.ExtractCrossJoinColumnName(sql, out var crossJoinColumnName);
841+
842+
while (await reader.ReadAsync(cancellationToken))
843+
{
844+
for (var i = 0; i < reader.FieldCount; i++)
845+
{
846+
var name = reader.GetName(i);
847+
848+
if (!string.IsNullOrEmpty(crossJoinColumnName) && name.Equals(crossJoinColumnName))
849+
{
850+
total = (int)reader[name];
851+
foundCrossJoinCountColumn = true;
852+
break;
853+
}
854+
}
855+
856+
list.Add(selectorFunc(mapper.Map(reader)));
857+
}
858+
859+
if (!foundCrossJoinCountColumn)
860+
total = list.Count;
861+
862+
return new PagedQueryResult<IEnumerable<TResult>>(list, total);
863+
}
811864
}
812865

813866
/// <summary>
@@ -880,10 +933,9 @@ public async Task<TEntity> FindAsync<TEntity>(CancellationToken cancellationToke
880933
options,
881934
out var sql,
882935
out var parameters,
883-
out var navigationProperties,
884-
out var getPropertyFromColumnAliasCallback);
936+
out var mappingProperties);
885937

886-
var mapper = new Mapper<TEntity>(Conventions, navigationProperties, getPropertyFromColumnAliasCallback);
938+
var mapper = new Mapper<TEntity>(Conventions, mappingProperties);
887939

888940
await ExecuteSchemaValidateAsync(typeof(TEntity), cancellationToken);
889941

@@ -909,7 +961,9 @@ public async Task<TEntity> FindAsync<TEntity>(CancellationToken cancellationToke
909961
}
910962
}
911963

912-
dict.Add(mapper.Map<TDictionaryKey>(reader, keySelectFunc), mapper.Map<TElement>(reader, elementSelectorFunc));
964+
var mapped = mapper.Map(reader);
965+
966+
dict.Add(keySelectFunc(mapped), elementSelectorFunc(mapped));
913967
}
914968

915969
if (!foundCrossJoinCountColumn)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace DotNetToolkit.Repository.AdoNet.Internal
2+
{
3+
using System;
4+
using System.Data.Common;
5+
6+
internal static class DbDataReaderExtensions
7+
{
8+
public static T GetValue<T>(this DbDataReader reader, int ordinal)
9+
{
10+
var value = reader.GetValue(ordinal);
11+
12+
if (value == null || value == DBNull.Value)
13+
{
14+
return default(T);
15+
}
16+
else
17+
{
18+
return (T)value;
19+
}
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)