Skip to content

Commit 4323c01

Browse files
committed
Add DataReader mapper to fill concrete types from database results
1 parent 756fcba commit 4323c01

File tree

18 files changed

+473
-5
lines changed

18 files changed

+473
-5
lines changed
31.7 KB
Binary file not shown.
20 KB
Binary file not shown.
22 KB
Binary file not shown.
22 KB
Binary file not shown.
78.8 KB
Binary file not shown.
91 KB
Binary file not shown.
91 KB
Binary file not shown.
19.6 KB
Binary file not shown.
33 KB
Binary file not shown.

src/Devlord.Utilities/DRMapper.cs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88

99
using System;
1010
using System.Collections.Generic;
11-
using System.Data.SqlClient;
11+
using System.Data;
12+
using System.Reflection;
13+
using Devlord.Utilities.Resources;
1214

1315
namespace Devlord.Utilities
1416
{
@@ -21,15 +23,17 @@ namespace Devlord.Utilities
2123
/// </remarks>
2224
public class DRMapper
2325
{
24-
public static List<T> ParseList<T>(SqlDataReader dr)
26+
public static List<T> ParseList<T>(IDataReader dr)
2527
{
2628
var list = new List<T>();
2729

2830
var properties = typeof(T).GetProperties();
29-
var instance = Activator.CreateInstance<T>();
31+
32+
VerifyTypeMatch<T>(dr, properties);
3033

3134
while (dr.Read())
3235
{
36+
var instance = Activator.CreateInstance<T>();
3337
foreach (var pi in properties)
3438
{
3539
pi.SetValue(instance, dr[pi.Name], null);
@@ -41,10 +45,41 @@ public static List<T> ParseList<T>(SqlDataReader dr)
4145
return list;
4246
}
4347

44-
public static T ParseRecord<T>(SqlDataReader dr, int rowIndex = 0)
48+
private static void VerifyTypeMatch<T>(IDataRecord dr, IEnumerable<PropertyInfo> properties)
49+
{
50+
// Counter for when each field is found.
51+
var dictionary = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
52+
53+
// Throw an error if the class expects columns that aren't being returned.
54+
foreach (var pi in properties)
55+
{
56+
// Increment
57+
dictionary.Add(pi.Name);
58+
}
59+
60+
// Don't throw an error if the data set more verbose than the class we're filling
61+
for (int i = 0; i < dr.FieldCount; i++)
62+
{
63+
// Decrement.
64+
string column = dr.GetName(i);
65+
if (dictionary.Contains(column))
66+
{
67+
dictionary.Remove(column);
68+
}
69+
}
70+
71+
if (dictionary.Count > 0)
72+
{
73+
var ex = new Exception(ExceptionText.DRMapperTypeTooComplex);
74+
ex.Data.Add("Type", typeof(T));
75+
ex.Data.Add("Missing fields", string.Join(", ", dictionary));
76+
throw ex;
77+
}
78+
}
79+
80+
public static T ParseRecord<T>(IDataReader dr, int rowIndex = 0)
4581
{
4682
var properties = typeof(T).GetProperties();
47-
var instance = Activator.CreateInstance<T>();
4883

4984
var currentRow = 0;
5085
while (dr.Read())
@@ -55,6 +90,7 @@ public static T ParseRecord<T>(SqlDataReader dr, int rowIndex = 0)
5590
continue;
5691
}
5792

93+
var instance = Activator.CreateInstance<T>();
5894
foreach (var pi in properties)
5995
{
6096
pi.SetValue(instance, dr[pi.Name], null);
@@ -63,6 +99,11 @@ public static T ParseRecord<T>(SqlDataReader dr, int rowIndex = 0)
6399
return instance;
64100
}
65101

102+
if (rowIndex > currentRow)
103+
{
104+
throw new IndexOutOfRangeException(ExceptionText.DRMapperIndexOutOfRange);
105+
}
106+
66107
return default(T);
67108
}
68109
}

0 commit comments

Comments
 (0)