dapper mysql tinyint_Error parsing column 8 (IsRecommended=0 - SByte) Dapper查询mysql数据库可空的tinyint(1)...

本文介绍了在使用Dapper查询MySQL数据库时遇到的TinyInt(1)类型转换错误,详细解析了错误原因并提供了解决方案,涉及到数据类型匹配、值类型转换和数据库字段映射等技术细节。
摘要由CSDN通过智能技术生成

private static FuncGetTypeDeserializerImpl(

Type type, IDataReader reader,int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false)

{var returnType = type.IsValueType() ? typeof(object) : type;var dm = new DynamicMethod("Deserialize" + Guid.NewGuid().ToString(), returnType, new[] { typeof(IDataReader) }, type, true);var il =dm.GetILGenerator();

il.DeclareLocal(typeof(int));

il.DeclareLocal(type);

il.Emit(OpCodes.Ldc_I4_0);

il.Emit(OpCodes.Stloc_0);if (length == -1)

{

length= reader.FieldCount -startBound;

}if (reader.FieldCount <=startBound)

{throwMultiMapException(reader);

}//数据库字段名

var fieldNames = Enumerable.Range(startBound, length).Select(i =>reader.GetName(i)).ToArray();//ITypeMap 含type的字段,属性

ITypeMap typeMap =GetTypeMap(type);int index =startBound;

ConstructorInfo specializedConstructor= null;#if !NETSTANDARD1_3

bool supportInitialize = false;#endifDictionary structLocals = null;if(type.IsValueType())

{

il.Emit(OpCodes.Ldloca_S, (byte)1);

il.Emit(OpCodes.Initobj, type);

}else{//字段映射,开始

var types = newType[length];for (int i = startBound; i < startBound + length; i++)

{

types[i- startBound] =reader.GetFieldType(i);

}//获取ExplicitConstructor特性的构造函数

var explicitConstr =typeMap.FindExplicitConstructor();if (explicitConstr != null)

{var consPs =explicitConstr.GetParameters();foreach (var p inconsPs)

{if (!p.ParameterType.IsValueType())

{

il.Emit(OpCodes.Ldnull);

}else{

GetTempLocal(il,ref structLocals, p.ParameterType, true);

}

}

il.Emit(OpCodes.Newobj, explicitConstr);

il.Emit(OpCodes.Stloc_1);#if !NETSTANDARD1_3supportInitialize= typeof(ISupportInitialize).IsAssignableFrom(type);if(supportInitialize)

{

il.Emit(OpCodes.Ldloc_1);

il.EmitCall(OpCodes.Callvirt,typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.BeginInit)), null);

}#endif}else{//按构造函数参数个数倒序排列,查找合适的构造函数

var ctor =typeMap.FindConstructor(fieldNames, types);if (ctor == null)

{string proposedTypes = "(" + string.Join(",", types.Select((t, i) => t.FullName + " " + fieldNames[i]).ToArray()) + ")";throw new InvalidOperationException($"A parameterless default constructor or one matching signature {proposedTypes} is required for {type.FullName} materialization");

}//无参构造

if (ctor.GetParameters().Length == 0)

{//用指定构造函数创建一个新实例,赋值给类型变量

il.Emit(OpCodes.Newobj, ctor);

il.Emit(OpCodes.Stloc_1);#if !NETSTANDARD1_3supportInitialize= typeof(ISupportInitialize).IsAssignableFrom(type);if(supportInitialize)

{//取type实例

il.Emit(OpCodes.Ldloc_1);//调用公共方法

il.EmitCall(OpCodes.Callvirt, typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.BeginInit)), null);

}#endif}else{

specializedConstructor=ctor;

}

}

}//try块开始

il.BeginExceptionBlock();//值类型

if(type.IsValueType())

{

il.Emit(OpCodes.Ldloca_S, (byte)1);//[target]

}else if (specializedConstructor == null)

{

il.Emit(OpCodes.Ldloc_1);//[target]

}//根据数据库字段名,查找传入类型中对应的属性Property,若没有则查找字段Field

var members = IsValueTuple(type) ? GetValueTupleMembers(type, fieldNames) : ((specializedConstructor != null

? fieldNames.Select(n =>typeMap.GetConstructorParameter(specializedConstructor, n))

: fieldNames.Select(n=>typeMap.GetMember(n))).ToList());//stack is now [target]

bool first = true;var allDone =il.DefineLabel();int enumDeclareLocal = -1, valueCopyLocal = il.DeclareLocal(typeof(object)).LocalIndex;bool applyNullSetting =Settings.ApplyNullValues;foreach (var item inmembers)

{if (item != null)

{if (specializedConstructor == null)

il.Emit(OpCodes.Dup);//stack is now [target][target]

Label isDbNullLabel =il.DefineLabel();

Label finishLabel=il.DefineLabel();//索引为0的参数即reader

il.Emit(OpCodes.Ldarg_0); //stack is now [target][target][reader]

EmitInt32(il, index); //stack is now [target][target][reader][index]

il.Emit(OpCodes.Dup);//stack is now [target][target][reader][index][index]

il.Emit(OpCodes.Stloc_0);//stack is now [target][target][reader][index]

il.Emit(OpCodes.Callvirt, getItem); //stack is now [target][target][value-as-object]

il.Emit(OpCodes.Dup); //stack is now [target][target][value-as-object][value-as-object]

StoreLocal(il, valueCopyLocal);//字段类型

Type colType = reader.GetFieldType(index);//tinyint(1) null//属性/字段类型

Type memberType = item.MemberType;//bool?

if (memberType == typeof(char) || memberType == typeof(char?))

{

il.EmitCall(OpCodes.Call,typeof(SqlMapper).GetMethod(

memberType== typeof(char) ? nameof(SqlMapper.ReadChar) : nameof(SqlMapper.ReadNullableChar), BindingFlags.Static | BindingFlags.Public), null); //stack is now [target][target][typed-value]

}else{

il.Emit(OpCodes.Dup);//stack is now [target][target][value][value]

il.Emit(OpCodes.Isinst, typeof(DBNull)); //stack is now [target][target][value-as-object][DBNull or null]//跳转到marklable

il.Emit(OpCodes.Brtrue_S, isDbNullLabel); //stack is now [target][target][value-as-object]//unbox nullable enums as the primitive, i.e. byte etc

var nullUnderlyingType =Nullable.GetUnderlyingType(memberType);var unboxType = nullUnderlyingType?.IsEnum() == true ?nullUnderlyingType : memberType;if(unboxType.IsEnum())

{

Type numericType=Enum.GetUnderlyingType(unboxType);if (colType == typeof(string))

{if (enumDeclareLocal == -1)

{

enumDeclareLocal= il.DeclareLocal(typeof(string)).LocalIndex;

}

il.Emit(OpCodes.Castclass,typeof(string)); //stack is now [target][target][string]

StoreLocal(il, enumDeclareLocal); //stack is now [target][target]

il.Emit(OpCodes.Ldtoken, unboxType); //stack is now [target][target][enum-type-token]

il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle)), null);//stack is now [target][target][enum-type]

LoadLocal(il, enumDeclareLocal); //stack is now [target][target][enum-type][string]

il.Emit(OpCodes.Ldc_I4_1); //stack is now [target][target][enum-type][string][true]

il.EmitCall(OpCodes.Call, enumParse, null); //stack is now [target][target][enum-as-object]

il.Emit(OpCodes.Unbox_Any, unboxType); //stack is now [target][target][typed-value]

}else{

FlexibleConvertBoxedFromHeadOfStack(il, colType, unboxType, numericType);

}if (nullUnderlyingType != null)

{

il.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType })); //stack is now [target][target][typed-value]

}

}else if (memberType.FullName ==LinqBinary)

{

il.Emit(OpCodes.Unbox_Any,typeof(byte[])); //stack is now [target][target][byte-array]

il.Emit(OpCodes.Newobj, memberType.GetConstructor(new Type[] { typeof(byte[]) }));//stack is now [target][target][binary]

}else{

TypeCode dataTypeCode= TypeExtensions.GetTypeCode(colType), unboxTypeCode =TypeExtensions.GetTypeCode(unboxType);boolhasTypeHandler;if ((hasTypeHandler = typeHandlers.ContainsKey(unboxType)) || colType == unboxType || dataTypeCode == unboxTypeCode || dataTypeCode ==TypeExtensions.GetTypeCode(nullUnderlyingType))

{if(hasTypeHandler)

{#pragma warning disable 618il.EmitCall(OpCodes.Call,typeof(TypeHandlerCache<>).MakeGenericType(unboxType).GetMethod(nameof(TypeHandlerCache.Parse)), null); //stack is now [target][target][typed-value]

#pragma warning restore 618}else{

il.Emit(OpCodes.Unbox_Any, unboxType);//stack is now [target][target][typed-value]

}

}else{//not a direct match; need to tweak the unbox

FlexibleConvertBoxedFromHeadOfStack(il, colType, nullUnderlyingType ?? unboxType, null);if (nullUnderlyingType != null)

{

il.Emit(OpCodes.Newobj, unboxType.GetConstructor(new[] { nullUnderlyingType })); //stack is now [target][target][typed-value]

}

}

}

}if (specializedConstructor == null)

{//Store the value in the property/field

if (item.Property != null)

{

il.Emit(type.IsValueType()?OpCodes.Call : OpCodes.Callvirt, DefaultTypeMap.GetPropertySetter(item.Property, type));

}else{

il.Emit(OpCodes.Stfld, item.Field);//stack is now [target]

}

}//跳转到finishLabel

il.Emit(OpCodes.Br_S, finishLabel); //stack is now [target]

il.MarkLabel(isDbNullLabel);//incoming stack: [target][target][value]

if (specializedConstructor != null)

{

il.Emit(OpCodes.Pop);if(item.MemberType.IsValueType())

{int localIndex =il.DeclareLocal(item.MemberType).LocalIndex;

LoadLocalAddress(il, localIndex);

il.Emit(OpCodes.Initobj, item.MemberType);

LoadLocal(il, localIndex);

}else{

il.Emit(OpCodes.Ldnull);

}

}else if (applyNullSetting && (!memberType.IsValueType() || Nullable.GetUnderlyingType(memberType) != null))

{

il.Emit(OpCodes.Pop);//stack is now [target][target]//can load a null with this value

if(memberType.IsValueType())

{//must be Nullable for some T

GetTempLocal(il, ref structLocals, memberType, true); //stack is now [target][target][null]

}else{//regular reference-type

il.Emit(OpCodes.Ldnull); //stack is now [target][target][null]

}//Store the value in the property/field

if (item.Property != null)

{

il.Emit(type.IsValueType()?OpCodes.Call : OpCodes.Callvirt, DefaultTypeMap.GetPropertySetter(item.Property, type));//stack is now [target]

}else{

il.Emit(OpCodes.Stfld, item.Field);//stack is now [target]

}

}else{

il.Emit(OpCodes.Pop);//stack is now [target][target]

il.Emit(OpCodes.Pop); //stack is now [target]

}if (first &&returnNullIfFirstMissing)

{

il.Emit(OpCodes.Pop);

il.Emit(OpCodes.Ldnull);//stack is now [null]

il.Emit(OpCodes.Stloc_1);

il.Emit(OpCodes.Br, allDone);

}

il.MarkLabel(finishLabel);

}

first= false;

index++;

}if(type.IsValueType())

{

il.Emit(OpCodes.Pop);

}else{if (specializedConstructor != null)

{

il.Emit(OpCodes.Newobj, specializedConstructor);

}

il.Emit(OpCodes.Stloc_1);//stack is empty

#if !NETSTANDARD1_3

if(supportInitialize)

{

il.Emit(OpCodes.Ldloc_1);

il.EmitCall(OpCodes.Callvirt,typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.EndInit)), null);

}#endif}

il.MarkLabel(allDone);

il.BeginCatchBlock(typeof(InvalidCastException)); //stack is Exception

il.Emit(OpCodes.Ldloc_0); //stack is Exception, index

il.Emit(OpCodes.Ldarg_0); //stack is Exception, index, reader

LoadLocal(il, valueCopyLocal); //stack is Exception, index, reader, value

il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod(nameof(SqlMapper.ThrowDataException)), null);

il.EndExceptionBlock();

il.Emit(OpCodes.Ldloc_1);//stack is [rval]

if(type.IsValueType())

{

il.Emit(OpCodes.Box, type);

}

il.Emit(OpCodes.Ret);var funcType = System.Linq.Expressions.Expression.GetFuncType(typeof(IDataReader), returnType);return (Func)dm.CreateDelegate(funcType);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值