当前位置: 首页 > 编程语言 > C#

检查数据库记录映射中的空值分享

时间:2023-04-10 19:27:23 C#

C#学习教程:检查数据库记录映射中的空值请理解我是一个新的C#转换...这段代码所做的是获取一个IDataReader对象并将其转换并映射到一个强类型的对象列表。但我发现当阅读器返回空列时,它就完全出错了。转换器internalclassConverterwhereT:new(){//声明我们的_converterdelegatereadonlyFunc_converter;//声明我们的内部dataReaderreadonlyIDataReaderdataReader;//根据我们传递给类的类/类型中的属性构建我们的映射privateFuncGetMapFunc(){//声明我们的字段计数int_fc=dataReader.FieldCount;//声明我们的表达式列表Listexps=newList();//为表达式树构建参数ParameterExpressionparamExp=Expression.Parameter(typeof(IDataRecord),"o7thDR");ParameterExpressiontargetExp=Expression.Variable(typeof(T));//将我们的表达式树赋值添加到exp列表exps.Add(Expression.Assign(targetExp,Expression.New(targetExp.Type)));//基于int的查找PropertyInfoindexerInfo=typeof(IDataRecord).GetProperty("Item",new[]{typeof(int)});//从我们的数据读取器中获取列名称的集合varcolumnNames=Enumerable.Range(0,_fc).Select(i=>new{i,name=dataReader.GetName(i)}).AsParallel();//遍历我们所有的列并正确映射它们;//检查它是否为空IndexExpressionpropertyExp=Expression.MakeIndex(paramExp,indexerInfo,new[]{columnNameExp});UnaryExpressionconvertExp=Expression.Convert(propertyExp,property.PropertyType);BinaryExpressionbindExp=Expression.Assign(Expression.Property(targetExp,property),convertExp);//将它添加到我们的表达式列表exps.Add(bindExp);}}//将原始映射添加到我们的表达式列表exps.Add(targetExp);//返回编译后的缓存映射returnExpression.Lambda(Expression.Block(new[]{targetExp},exps),paramExp).Compile();}//初始化内部Converter(IDataReaderdataReader){//初始化内部数据读取器this.dataReader=dataReader;//构建我们的地图_converter=GetMapFunc();}//创建并将每一列映射到它各自的对象internalTCreateItemFromRow(){return_converter(dataReader);}}mapperprivatestaticIListMap(DbDataReaderdr)whereT:new(){try{//初始化我们的可返回列表Listlist=newList();//启动lamda映射varconverter=newConverter(dr);while(dr.Read()){//读取每一行,并将其正确映射到我们的T对象varobj=converter.CreateItemFromRow();//将它添加到我们的列表list.Add(obj);}//reutrn返回列表;}catch(Exceptionex){//确保此方法返回默认列表returndefault(List);我只是不太明白列类型对象在这里发生了什么,所以我会尝试自己做......但我只是不知道它在哪里我知道这可能没什么帮助,但我得到的错误是:无法将类型为“System.DBNull”的对象转换为类型“System.String”。它发生在内部TCreateItemFromRow(){return_converter(dataReader);//<--Here}请注意,如果我使用ISNULL(column,")将查询本身中的列包装起来,则不会发生这种情况,但我相信您可以理解这绝对不是解决方案问题出在convertExp=Expression.Convert(propertyExp,property.PropertyType)。您不能指望将DbNull值转换为框架类型中的等效值。当您的类型是值类型时,这尤其令人讨厌。一种选择是检查db中的读取该值是否为DbNull.Value,如果是,您需要自己寻找一个兼容的值。在某些情况下,可以使用C#中这些类型的默认值。如果你必须做property=value==DBNull.Value?默认值(T):值;通用实现看起来像(转换器类中的foreach):foreach(列中的var列){varproperty=targetExp.Type。GetProperty(column.name,BindingFlags.Public|BindingFlags.Instance|BindingFlags.IgnoreCase);如果(属性==null)继续;varcolumnIndexExp=Expression.Constant(column.i);varpropertyExp=Expression.MakeIndex(paramExp,indexerInfo,new[]{columnIndexExp});varconvertExp=Expression.Condition(Expression.Equal(propertyExp,Expression.Constant(DBNull.Value)),Expression.Default(property.PropertyType),Expression.Convert(propertyExp,property.PropertyType));varbindExp=Expression.Assign(Expression.Property(targetExp,property),convertExp);exps.Add(bindExp);现在这相当于property=reader[index]==DBNull.Value?默认(T):阅读器[索引];您可以通过将读取器分配给一个变量并在条件检查中使用它的值来避免对读取器进行双重查找。所以这应该稍微好一点,但更复杂:如果(属性==null)继续;varcolumnIndexExp=Expression.Constant(column.i);varcellExp=Expression.MakeIndex(paramExp,indexerInfo,new[]{columnIndexExp});varcellValueExp=Expression.Variable(typeof(object),"o7thPropValue");varconvertExp=Expression.Condition(Expression.Equal(cellValueExp,Expression.Constant(DBNull.Value)),Expression.Default(property.PropertyType),Expression.Convert(cellValueExp,property.PropertyType));varcellValueReadExp=Expression.Block(new[]{cellValueExp},Expression.Assign(cellValueExp,cellExp),convertExp);varbindExp=Expression.Assign(Expression.Property(targetExp,property),cellValueReadExp);exps.Add(bindExp);这个条件检查是这样完成的:value=reader[index];属性=值==DBNull.Value?默认值(T):值;这是处理一般数据集时最烦人的问题之一。我通常解决它的方法是将DBNull值转换为更有用的东西,例如在某些情况下实际为null甚至空字符串。这可以通过多种方式完成,但最近我采用了扩展方法。公共静态T?GetValueOrNull(thisobjectvalue)whereT:struct{返回值==null||值==DBNull.Value?(T?)null:(T)Convert.ChangeType(value,typeof(T));}可空类型的便捷扩展方法,例如:int?myInt=DataSet.Tables[0].Rows[0]["DBNullInt"].GetValueOrNull();或者更一般地只是将DBNull转换为null:publicstaticobjectGetValueOrNull(thisobjectvalue){returnvalue==DBNull.Value?空值:值;}字符串myStringDataSet.Tables[0].Rows[0]["DBNullString"].GetValueOrNull();然后你会得到一个空字符串,而不是试图将DBNull放入一个字符串中。希望这对你有帮助。以上就是C#学习教程:检查数据库记录映射中空值的所有内容分享,如果对您有用,还需要进一步了解C#学习教程,希望大家多加关注——本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处: