Как проверить нулевые значения db в прилагаемом коде? Пожалуйста, поймите, что я новый конвертер C# ...Проверка нулей на картографировании записей DB
Что делает этот код, он принимает объект IDataReader и преобразовывает его в строго типизированный список объектов. Но то, что я нахожу, это полностью ошибки, когда в читателе возвращаются нулевые столбцы.
конвертер
internal class Converter<T> where T : new()
{
// Declare our _converter delegate
readonly Func<IDataReader, T> _converter;
// Declare our internal dataReader
readonly IDataReader dataReader;
// Build our mapping based on the properties in the class/type we've passed in to the class
private Func<IDataReader, T> GetMapFunc()
{
// declare our field count
int _fc = dataReader.FieldCount;
// declare our expression list
List<Expression> exps = new List<Expression>();
// build our parameters for the expression tree
ParameterExpression paramExp = Expression.Parameter(typeof(IDataRecord), "o7thDR");
ParameterExpression targetExp = Expression.Variable(typeof(T));
// Add our expression tree assignment to the exp list
exps.Add(Expression.Assign(targetExp, Expression.New(targetExp.Type)));
//does int based lookup
PropertyInfo indexerInfo = typeof(IDataRecord).GetProperty("Item", new[] { typeof(int) });
// grab a collection of column names from our data reader
var columnNames = Enumerable.Range(0, _fc).Select(i => new { i, name = dataReader.GetName(i) }).AsParallel();
// loop through all our columns and map them properly
foreach (var column in columnNames)
{
// grab our column property
PropertyInfo property = targetExp.Type.GetProperty(column.name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
// check if it's null or not
if (property != null)
{
// build our expression tree to map the column to the T
ConstantExpression columnNameExp = Expression.Constant(column.i);
IndexExpression propertyExp = Expression.MakeIndex(paramExp, indexerInfo, new[] { columnNameExp });
UnaryExpression convertExp = Expression.Convert(propertyExp, property.PropertyType);
BinaryExpression bindExp = Expression.Assign(Expression.Property(targetExp, property), convertExp);
// add it to our expression list
exps.Add(bindExp);
}
}
// add the originating map to our expression list
exps.Add(targetExp);
// return a compiled cached map
return Expression.Lambda<Func<IDataReader, T>>(Expression.Block(new[] { targetExp }, exps), paramExp).Compile();
}
// initialize
internal Converter(IDataReader dataReader)
{
// initialize the internal datareader
this.dataReader = dataReader;
// build our map
_converter = GetMapFunc();
}
// create and map each column to it's respective object
internal T CreateItemFromRow()
{
return _converter(dataReader);
}
}
Mapper
private static IList<T> Map<T>(DbDataReader dr) where T : new()
{
try
{
// initialize our returnable list
List<T> list = new List<T>();
// fire up the lamda mapping
var converter = new Converter<T>(dr);
while (dr.Read())
{
// read in each row, and properly map it to our T object
var obj = converter.CreateItemFromRow();
// add it to our list
list.Add(obj);
}
// reutrn it
return list;
}
catch (Exception ex)
{
// make sure this method returns a default List
return default(List<T>);
}
}
Я просто не совсем понимаю, где столбец напечатал объект происходит здесь, так что я бы попытаться сделать это сам ... но Я просто не знаю, где это.
Я знаю, что это, вероятно, не поможет, но ошибка я получаю:
Unable to cast object of type 'System.DBNull' to type 'System.String'.
, и это происходит на
internal T CreateItemFromRow()
{
return _converter(dataReader); //<-- Here
}
Примечание
Это делает не произойдет, если я обернут столбцы в самом запросе ISNULL (столбец, ''), но я уверен, что вы можете понять, что это, безусловно, не решение
Sure. Легко обойти для ссылочных типов. Но как это делается для типов значений? Как следует обрабатывать DbNulls? Может быть, вы хотите, чтобы значение по умолчанию возвращалось по типу, но как вы можете быть уверены, что так оно и должно быть обработано каждый раз? Что делать, если вы не хотите значения по умолчанию, а что-то еще? В таких случаях мы можем передать определенные правила, нужно ли нам добавить условие для перегрузки или что-то еще? – nawfal
Ну ... Я думаю, если бы я понял это лучше, я, вероятно, мог бы найти лучший способ справиться с ними, но теперь я думаю, что «значение по умолчанию для типа» было бы лучшим способом с этим ... на по крайней мере, это мои мысли об этом на данный момент :) Как я уже сказал, как только я смогу это понять, я всегда мог бы построить расширение для этого, чтобы обработать потенциал для указанных значений 'default' ... но я не знаю, где посмотрите LOL – Kevin
справедливая точка! дайте мне некоторое время, я добавлю ответ в течение дня или около того. Просто слишком занят работой на данный момент :) Проблема здесь: 'convertExp = Expression.Convert (propertyExp, property.PropertyType)'. Вы не можете ожидать преобразования DbNull в типы фреймов. Перед этим вам нужна функция GetValueOrDefault, чтобы проверить значение. – nawfal