2017-01-07 21:54:51 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Data;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Reflection.Emit;
|
2017-07-09 18:14:33 +08:00
|
|
|
|
using System.Text.RegularExpressions;
|
2023-04-25 13:16:05 +08:00
|
|
|
|
using System.Xml.Linq;
|
2017-07-09 18:14:33 +08:00
|
|
|
|
|
2017-01-07 21:54:51 +08:00
|
|
|
|
namespace SqlSugar
|
|
|
|
|
{
|
2017-04-23 14:48:57 +08:00
|
|
|
|
///<summary>
|
|
|
|
|
/// ** description:IDataReader Entity Builder
|
|
|
|
|
/// ** author:sunkaixuan
|
|
|
|
|
/// ** date:2017/4/2
|
|
|
|
|
/// ** qq:610262374
|
|
|
|
|
/// </summary>
|
2017-04-23 02:57:59 +08:00
|
|
|
|
public partial class IDataReaderEntityBuilder<T>
|
2017-01-07 21:54:51 +08:00
|
|
|
|
{
|
2017-05-28 18:49:49 +08:00
|
|
|
|
#region Properies
|
2017-04-24 00:56:18 +08:00
|
|
|
|
private List<string> ReaderKeys { get; set; }
|
2017-05-28 18:49:49 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Fields
|
2019-05-11 14:39:00 +08:00
|
|
|
|
private SqlSugarProvider Context = null;
|
2017-06-19 01:51:52 +08:00
|
|
|
|
private IDataReaderEntityBuilder<T> DynamicBuilder;
|
|
|
|
|
private IDataRecord DataRecord;
|
2017-01-07 21:54:51 +08:00
|
|
|
|
private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getBoolean = typeof(IDataRecord).GetMethod("GetBoolean", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getByte = typeof(IDataRecord).GetMethod("GetByte", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getDateTime = typeof(IDataRecord).GetMethod("GetDateTime", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getDecimal = typeof(IDataRecord).GetMethod("GetDecimal", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getDouble = typeof(IDataRecord).GetMethod("GetDouble", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getFloat = typeof(IDataRecord).GetMethod("GetFloat", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getGuid = typeof(IDataRecord).GetMethod("GetGuid", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getInt16 = typeof(IDataRecord).GetMethod("GetInt16", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getInt32 = typeof(IDataRecord).GetMethod("GetInt32", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getInt64 = typeof(IDataRecord).GetMethod("GetInt64", new Type[] { typeof(int) });
|
|
|
|
|
private static readonly MethodInfo getString = typeof(IDataRecord).GetMethod("GetString", new Type[] { typeof(int) });
|
2021-02-04 21:47:14 +08:00
|
|
|
|
//private static readonly MethodInfo getConvertValueMethod = typeof(IDataRecordExtensions).GetMethod("GetConvertValue");
|
2017-09-20 12:44:10 +08:00
|
|
|
|
private static readonly MethodInfo getdatetimeoffset = typeof(IDataRecordExtensions).GetMethod("Getdatetimeoffset");
|
|
|
|
|
private static readonly MethodInfo getdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod("GetdatetimeoffsetDate");
|
2017-06-25 23:42:53 +08:00
|
|
|
|
private static readonly MethodInfo getStringGuid = typeof(IDataRecordExtensions).GetMethod("GetStringGuid");
|
2022-05-14 17:23:35 +08:00
|
|
|
|
private static readonly MethodInfo getXelement = typeof(IDataRecordExtensions).GetMethod("GetXelement");
|
2017-06-25 23:42:53 +08:00
|
|
|
|
private static readonly MethodInfo getConvertStringGuid = typeof(IDataRecordExtensions).GetMethod("GetConvertStringGuid");
|
2017-06-04 19:22:05 +08:00
|
|
|
|
private static readonly MethodInfo getEnum = typeof(IDataRecordExtensions).GetMethod("GetEnum");
|
2017-06-07 14:25:33 +08:00
|
|
|
|
private static readonly MethodInfo getConvertString = typeof(IDataRecordExtensions).GetMethod("GetConvertString");
|
2017-01-07 21:54:51 +08:00
|
|
|
|
private static readonly MethodInfo getConvertFloat = typeof(IDataRecordExtensions).GetMethod("GetConvertFloat");
|
|
|
|
|
private static readonly MethodInfo getConvertBoolean = typeof(IDataRecordExtensions).GetMethod("GetConvertBoolean");
|
|
|
|
|
private static readonly MethodInfo getConvertByte = typeof(IDataRecordExtensions).GetMethod("GetConvertByte");
|
|
|
|
|
private static readonly MethodInfo getConvertChar = typeof(IDataRecordExtensions).GetMethod("GetConvertChar");
|
|
|
|
|
private static readonly MethodInfo getConvertDateTime = typeof(IDataRecordExtensions).GetMethod("GetConvertDateTime");
|
2018-04-08 16:31:27 +08:00
|
|
|
|
private static readonly MethodInfo getConvertTime = typeof(IDataRecordExtensions).GetMethod("GetConvertTime");
|
|
|
|
|
private static readonly MethodInfo getTime = typeof(IDataRecordExtensions).GetMethod("GetTime");
|
2017-01-07 21:54:51 +08:00
|
|
|
|
private static readonly MethodInfo getConvertDecimal = typeof(IDataRecordExtensions).GetMethod("GetConvertDecimal");
|
|
|
|
|
private static readonly MethodInfo getConvertDouble = typeof(IDataRecordExtensions).GetMethod("GetConvertDouble");
|
2018-11-26 00:13:18 +08:00
|
|
|
|
private static readonly MethodInfo getConvertDoubleToFloat = typeof(IDataRecordExtensions).GetMethod("GetConvertDoubleToFloat");
|
2017-01-07 21:54:51 +08:00
|
|
|
|
private static readonly MethodInfo getConvertGuid = typeof(IDataRecordExtensions).GetMethod("GetConvertGuid");
|
|
|
|
|
private static readonly MethodInfo getConvertInt16 = typeof(IDataRecordExtensions).GetMethod("GetConvertInt16");
|
|
|
|
|
private static readonly MethodInfo getConvertInt32 = typeof(IDataRecordExtensions).GetMethod("GetConvertInt32");
|
2017-07-11 22:06:05 +08:00
|
|
|
|
private static readonly MethodInfo getConvertInt64 = typeof(IDataRecordExtensions).GetMethod("GetConvetInt64");
|
2017-01-07 21:54:51 +08:00
|
|
|
|
private static readonly MethodInfo getConvertEnum_Null = typeof(IDataRecordExtensions).GetMethod("GetConvertEnum_Null");
|
2017-09-20 12:44:10 +08:00
|
|
|
|
private static readonly MethodInfo getConvertdatetimeoffset = typeof(IDataRecordExtensions).GetMethod("GetConvertdatetimeoffset");
|
|
|
|
|
private static readonly MethodInfo getConvertdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod("GetConvertdatetimeoffsetDate");
|
2017-01-07 21:54:51 +08:00
|
|
|
|
private static readonly MethodInfo getOtherNull = typeof(IDataRecordExtensions).GetMethod("GetOtherNull");
|
|
|
|
|
private static readonly MethodInfo getOther = typeof(IDataRecordExtensions).GetMethod("GetOther");
|
2019-05-16 20:25:11 +08:00
|
|
|
|
private static readonly MethodInfo getJson = typeof(IDataRecordExtensions).GetMethod("GetJson");
|
2020-10-13 18:14:16 +08:00
|
|
|
|
private static readonly MethodInfo getArray = typeof(IDataRecordExtensions).GetMethod("GetArray");
|
2019-05-11 14:39:00 +08:00
|
|
|
|
private static readonly MethodInfo getEntity = typeof(IDataRecordExtensions).GetMethod("GetEntity", new Type[] { typeof(SqlSugarProvider) });
|
2024-05-08 18:27:23 +08:00
|
|
|
|
private static readonly MethodInfo getMyIntNull = typeof(IDataRecordExtensions).GetMethod("GetMyIntNull");
|
|
|
|
|
private static readonly MethodInfo getMyInt= typeof(IDataRecordExtensions).GetMethod("GetMyInt");
|
2017-09-20 12:44:10 +08:00
|
|
|
|
|
2017-01-07 21:54:51 +08:00
|
|
|
|
private delegate T Load(IDataRecord dataRecord);
|
|
|
|
|
private Load handler;
|
|
|
|
|
#endregion
|
|
|
|
|
|
2017-06-19 01:51:52 +08:00
|
|
|
|
#region Constructor
|
|
|
|
|
private IDataReaderEntityBuilder()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-15 16:24:07 +08:00
|
|
|
|
public IDataReaderEntityBuilder(SqlSugarProvider context, IDataRecord dataRecord, List<string> fieldNames)
|
2017-06-19 01:51:52 +08:00
|
|
|
|
{
|
|
|
|
|
this.Context = context;
|
|
|
|
|
this.DataRecord = dataRecord;
|
|
|
|
|
this.DynamicBuilder = new IDataReaderEntityBuilder<T>();
|
2017-11-23 16:19:33 +08:00
|
|
|
|
this.ReaderKeys = fieldNames;
|
2017-06-19 01:51:52 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
2017-05-28 18:49:49 +08:00
|
|
|
|
#region Public methods
|
2017-01-07 21:54:51 +08:00
|
|
|
|
public T Build(IDataRecord dataRecord)
|
|
|
|
|
{
|
|
|
|
|
return handler(dataRecord);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-23 14:30:42 +08:00
|
|
|
|
public IDataReaderEntityBuilder<T> CreateBuilder(Type type)
|
2017-01-07 21:54:51 +08:00
|
|
|
|
{
|
2017-04-23 14:30:42 +08:00
|
|
|
|
DynamicMethod method = new DynamicMethod("SqlSugarEntity", type,
|
2017-01-07 21:54:51 +08:00
|
|
|
|
new Type[] { typeof(IDataRecord) }, type, true);
|
|
|
|
|
ILGenerator generator = method.GetILGenerator();
|
|
|
|
|
LocalBuilder result = generator.DeclareLocal(type);
|
2022-08-12 15:44:20 +08:00
|
|
|
|
generator.Emit(OpCodes.Newobj, type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
|
|
|
|
|
null, Type.EmptyTypes, null));
|
2017-01-07 21:54:51 +08:00
|
|
|
|
generator.Emit(OpCodes.Stloc, result);
|
2019-05-17 20:34:53 +08:00
|
|
|
|
this.Context.InitMappingInfo(type);
|
2023-06-29 18:58:04 +08:00
|
|
|
|
var columnInfos = this.Context.EntityMaintenance.GetEntityInfoWithAttr(type).Columns;
|
2019-05-16 17:40:55 +08:00
|
|
|
|
foreach (var columnInfo in columnInfos)
|
2017-01-07 21:54:51 +08:00
|
|
|
|
{
|
2019-05-16 17:40:55 +08:00
|
|
|
|
string fileName = columnInfo.DbColumnName ?? columnInfo.PropertyName;
|
2019-07-15 16:24:07 +08:00
|
|
|
|
if (columnInfo.IsIgnore && !this.ReaderKeys.Any(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)))
|
2017-04-23 14:07:04 +08:00
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-02-05 20:06:39 +08:00
|
|
|
|
else if (columnInfo.ForOwnsOnePropertyInfo!=null)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-12-31 15:35:10 +08:00
|
|
|
|
if (columnInfo != null && columnInfo.PropertyInfo.GetSetMethod(true) != null)
|
2017-01-07 21:54:51 +08:00
|
|
|
|
{
|
2021-11-04 18:59:18 +08:00
|
|
|
|
var isGemo = columnInfo.PropertyInfo?.PropertyType?.FullName=="NetTopologySuite.Geometries.Geometry";
|
2025-04-20 19:23:22 +08:00
|
|
|
|
if (isGemo == false && columnInfo.PropertyInfo?.PropertyType?.FullName == "Kdbndp.LegacyPostgis.PostgisGeometry")
|
|
|
|
|
{
|
|
|
|
|
isGemo = true;
|
|
|
|
|
}
|
2021-11-04 18:59:18 +08:00
|
|
|
|
if (!isGemo&&columnInfo.PropertyInfo.PropertyType.IsClass() && columnInfo.PropertyInfo.PropertyType != UtilConstants.ByteArrayType && columnInfo.PropertyInfo.PropertyType != UtilConstants.ObjType)
|
2017-04-23 14:07:04 +08:00
|
|
|
|
{
|
2019-05-16 19:38:56 +08:00
|
|
|
|
if (this.ReaderKeys.Any(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)))
|
|
|
|
|
{
|
2019-07-15 16:24:07 +08:00
|
|
|
|
BindClass(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)));
|
2019-05-16 19:38:56 +08:00
|
|
|
|
}
|
2022-08-16 18:14:00 +08:00
|
|
|
|
else if (this.ReaderKeys.Any(it => it.Equals(columnInfo.PropertyName, StringComparison.CurrentCultureIgnoreCase)))
|
|
|
|
|
{
|
|
|
|
|
BindClass(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(columnInfo.PropertyName, StringComparison.CurrentCultureIgnoreCase)));
|
|
|
|
|
}
|
2017-04-23 14:07:04 +08:00
|
|
|
|
}
|
2021-11-11 12:02:46 +08:00
|
|
|
|
else if (!isGemo && columnInfo.IsJson && columnInfo.PropertyInfo.PropertyType != UtilConstants.StringType)
|
2021-11-11 12:03:52 +08:00
|
|
|
|
{ //json is struct
|
2021-11-11 12:02:46 +08:00
|
|
|
|
if (this.ReaderKeys.Any(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)))
|
|
|
|
|
{
|
|
|
|
|
BindClass(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)));
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-23 14:07:04 +08:00
|
|
|
|
else
|
|
|
|
|
{
|
2017-04-24 00:56:18 +08:00
|
|
|
|
if (this.ReaderKeys.Any(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)))
|
|
|
|
|
{
|
2019-05-16 17:47:38 +08:00
|
|
|
|
BindField(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)));
|
2017-04-24 00:56:18 +08:00
|
|
|
|
}
|
2020-11-22 13:58:51 +08:00
|
|
|
|
else if (this.ReaderKeys.Any(it => it.Equals(columnInfo.PropertyName, StringComparison.CurrentCultureIgnoreCase)))
|
|
|
|
|
{
|
|
|
|
|
BindField(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(columnInfo.PropertyName, StringComparison.CurrentCultureIgnoreCase)));
|
|
|
|
|
}
|
2017-04-23 14:07:04 +08:00
|
|
|
|
}
|
2017-01-07 21:54:51 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
generator.Emit(OpCodes.Ldloc, result);
|
|
|
|
|
generator.Emit(OpCodes.Ret);
|
2017-04-23 14:07:04 +08:00
|
|
|
|
DynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load));
|
|
|
|
|
return DynamicBuilder;
|
2017-06-07 02:12:04 +08:00
|
|
|
|
}
|
2017-11-23 16:07:02 +08:00
|
|
|
|
|
2017-05-28 18:49:49 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Private methods
|
2023-03-04 16:26:47 +08:00
|
|
|
|
private void BindCustomFunc(ILGenerator generator, LocalBuilder result, EntityColumnInfo columnInfo, string fieldName)
|
|
|
|
|
{
|
|
|
|
|
int i = DataRecord.GetOrdinal(fieldName);
|
|
|
|
|
Label endIfLabel = generator.DefineLabel();
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, isDBNullMethod);
|
|
|
|
|
generator.Emit(OpCodes.Brtrue, endIfLabel);
|
|
|
|
|
generator.Emit(OpCodes.Ldloc, result);
|
|
|
|
|
//generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
//generator.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
var method = (columnInfo.SqlParameterDbType as Type).GetMethod("QueryConverter");
|
|
|
|
|
method = method.MakeGenericMethod(new Type[] { columnInfo.PropertyInfo.PropertyType });
|
|
|
|
|
Type type = (columnInfo.SqlParameterDbType as Type);
|
|
|
|
|
//ConstructorInfo info = type.GetConstructor(Type.EmptyTypes);
|
|
|
|
|
//il.Emit(OpCodes.Newobj, info);
|
2023-04-25 13:16:05 +08:00
|
|
|
|
generator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
|
2023-03-04 16:26:47 +08:00
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
2023-04-25 13:16:05 +08:00
|
|
|
|
//method = (columnInfo.SqlParameterDbType as Type).GetMethod("QueryConverter");
|
|
|
|
|
//method = method.MakeGenericMethod(new Type[] { columnInfo.PropertyInfo.PropertyType });
|
2023-03-04 16:26:47 +08:00
|
|
|
|
if (method.IsVirtual)
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, method);
|
|
|
|
|
else
|
|
|
|
|
generator.Emit(OpCodes.Call, method);
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, columnInfo.PropertyInfo.GetSetMethod(true));
|
|
|
|
|
generator.MarkLabel(endIfLabel);
|
|
|
|
|
}
|
2019-05-16 19:38:56 +08:00
|
|
|
|
private void BindClass(ILGenerator generator, LocalBuilder result, EntityColumnInfo columnInfo, string fieldName)
|
2017-04-23 14:07:04 +08:00
|
|
|
|
{
|
2023-03-04 16:26:47 +08:00
|
|
|
|
|
|
|
|
|
if (columnInfo.SqlParameterDbType is Type)
|
|
|
|
|
{
|
|
|
|
|
BindCustomFunc(generator, result, columnInfo, fieldName);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-16 19:38:56 +08:00
|
|
|
|
if (columnInfo.IsJson)
|
|
|
|
|
{
|
2019-05-16 20:25:11 +08:00
|
|
|
|
MethodInfo jsonMethod = getJson.MakeGenericMethod(columnInfo.PropertyInfo.PropertyType);
|
2019-05-16 19:38:56 +08:00
|
|
|
|
int i = DataRecord.GetOrdinal(fieldName);
|
|
|
|
|
Label endIfLabel = generator.DefineLabel();
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, isDBNullMethod);
|
|
|
|
|
generator.Emit(OpCodes.Brtrue, endIfLabel);
|
|
|
|
|
generator.Emit(OpCodes.Ldloc, result);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
2025-06-26 10:38:58 +08:00
|
|
|
|
var insertBuilder = InstanceFactory.GetInsertBuilder(this.Context?.CurrentConnectionConfig);
|
|
|
|
|
if (insertBuilder?.DeserializeObjectFunc != null)
|
|
|
|
|
{
|
|
|
|
|
if (IDataRecordExtensions.DeserializeObjectFunc == null)
|
|
|
|
|
{
|
|
|
|
|
IDataRecordExtensions.DeserializeObjectFunc = insertBuilder.DeserializeObjectFunc;
|
|
|
|
|
}
|
|
|
|
|
jsonMethod =typeof(IDataRecordExtensions).GetMethod("GetDeserializeObject").MakeGenericMethod(columnInfo.PropertyInfo.PropertyType);
|
|
|
|
|
}
|
2019-05-16 20:25:11 +08:00
|
|
|
|
generator.Emit(OpCodes.Call, jsonMethod);
|
2019-12-31 15:35:10 +08:00
|
|
|
|
generator.Emit(OpCodes.Callvirt, columnInfo.PropertyInfo.GetSetMethod(true));
|
2019-05-16 19:38:56 +08:00
|
|
|
|
generator.MarkLabel(endIfLabel);
|
|
|
|
|
}
|
2020-10-13 18:14:16 +08:00
|
|
|
|
if (columnInfo.IsArray)
|
|
|
|
|
{
|
|
|
|
|
MethodInfo arrayMehtod = getArray.MakeGenericMethod(columnInfo.PropertyInfo.PropertyType);
|
|
|
|
|
int i = DataRecord.GetOrdinal(fieldName);
|
|
|
|
|
Label endIfLabel = generator.DefineLabel();
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, isDBNullMethod);
|
|
|
|
|
generator.Emit(OpCodes.Brtrue, endIfLabel);
|
|
|
|
|
generator.Emit(OpCodes.Ldloc, result);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
generator.Emit(OpCodes.Call, arrayMehtod);
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, columnInfo.PropertyInfo.GetSetMethod(true));
|
|
|
|
|
generator.MarkLabel(endIfLabel);
|
|
|
|
|
}
|
2023-03-04 16:26:47 +08:00
|
|
|
|
else if (columnInfo.UnderType == typeof(XElement))
|
2022-05-14 17:23:35 +08:00
|
|
|
|
{
|
|
|
|
|
int i = DataRecord.GetOrdinal(fieldName);
|
|
|
|
|
Label endIfLabel = generator.DefineLabel();
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, isDBNullMethod);
|
|
|
|
|
generator.Emit(OpCodes.Brtrue, endIfLabel);
|
|
|
|
|
generator.Emit(OpCodes.Ldloc, result);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
BindMethod(generator, columnInfo, i);
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, columnInfo.PropertyInfo.GetSetMethod(true));
|
|
|
|
|
generator.MarkLabel(endIfLabel);
|
2023-03-03 22:48:50 +08:00
|
|
|
|
}
|
2017-04-23 14:07:04 +08:00
|
|
|
|
}
|
2019-05-16 17:47:38 +08:00
|
|
|
|
private void BindField(ILGenerator generator, LocalBuilder result, EntityColumnInfo columnInfo, string fieldName)
|
2017-04-23 14:07:04 +08:00
|
|
|
|
{
|
2023-03-08 00:39:38 +08:00
|
|
|
|
if (columnInfo.SqlParameterDbType is Type)
|
2023-03-04 16:26:47 +08:00
|
|
|
|
{
|
|
|
|
|
BindCustomFunc(generator,result, columnInfo, fieldName);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-05-16 17:42:30 +08:00
|
|
|
|
int i = DataRecord.GetOrdinal(fieldName);
|
2017-04-23 14:07:04 +08:00
|
|
|
|
Label endIfLabel = generator.DefineLabel();
|
2023-03-08 00:39:38 +08:00
|
|
|
|
|
|
|
|
|
//2023-3-8
|
|
|
|
|
Label tryStart = generator.BeginExceptionBlock();//begin try
|
|
|
|
|
//2023-3-8
|
|
|
|
|
|
2017-04-23 14:07:04 +08:00
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, isDBNullMethod);
|
|
|
|
|
generator.Emit(OpCodes.Brtrue, endIfLabel);
|
|
|
|
|
generator.Emit(OpCodes.Ldloc, result);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldc_I4, i);
|
2019-05-16 17:47:38 +08:00
|
|
|
|
BindMethod(generator, columnInfo, i);
|
2019-12-31 15:35:10 +08:00
|
|
|
|
generator.Emit(OpCodes.Callvirt, columnInfo.PropertyInfo.GetSetMethod(true));
|
2017-04-23 14:07:04 +08:00
|
|
|
|
generator.MarkLabel(endIfLabel);
|
2023-03-08 00:39:38 +08:00
|
|
|
|
|
|
|
|
|
//2023-3-8
|
|
|
|
|
generator.Emit(OpCodes.Leave, tryStart);//eng try
|
|
|
|
|
generator.BeginCatchBlock(typeof(Exception));//begin catch
|
|
|
|
|
generator.Emit(OpCodes.Ldstr, ErrorMessage.GetThrowMessage($"{columnInfo.EntityName} {columnInfo.PropertyName} bind error", $"{columnInfo.PropertyName}绑定到{columnInfo.EntityName}失败,可以试着换一个类型,或者使用ORM自定义类型实现"));//thow message
|
|
|
|
|
generator.Emit(OpCodes.Newobj, typeof(Exception).GetConstructor(new Type[] { typeof(string) }));
|
|
|
|
|
generator.Emit(OpCodes.Throw);
|
|
|
|
|
generator.EndExceptionBlock();
|
|
|
|
|
//2023-3-8
|
2017-04-23 02:57:59 +08:00
|
|
|
|
}
|
2019-05-16 17:47:38 +08:00
|
|
|
|
private void BindMethod(ILGenerator generator, EntityColumnInfo columnInfo, int ordinal)
|
2017-01-07 21:54:51 +08:00
|
|
|
|
{
|
2017-06-07 02:12:04 +08:00
|
|
|
|
IDbBind bind = Context.Ado.DbBind;
|
|
|
|
|
bool isNullableType = false;
|
|
|
|
|
MethodInfo method = null;
|
2019-05-16 17:47:38 +08:00
|
|
|
|
Type bindPropertyType = UtilMethods.GetUnderType(columnInfo.PropertyInfo, ref isNullableType);
|
2017-10-10 14:41:08 +08:00
|
|
|
|
string dbTypeName = UtilMethods.GetParenthesesValue(DataRecord.GetDataTypeName(ordinal));
|
2019-07-15 16:24:07 +08:00
|
|
|
|
if (dbTypeName.IsNullOrEmpty())
|
|
|
|
|
{
|
2018-04-21 14:26:53 +08:00
|
|
|
|
dbTypeName = bindPropertyType.Name;
|
|
|
|
|
}
|
2019-05-16 17:47:38 +08:00
|
|
|
|
string propertyName = columnInfo.PropertyName;
|
2017-06-07 02:12:04 +08:00
|
|
|
|
string validPropertyName = bind.GetPropertyTypeName(dbTypeName);
|
|
|
|
|
validPropertyName = validPropertyName == "byte[]" ? "byteArray" : validPropertyName;
|
|
|
|
|
CSharpDataType validPropertyType = (CSharpDataType)Enum.Parse(typeof(CSharpDataType), validPropertyName);
|
2017-07-09 19:12:41 +08:00
|
|
|
|
|
2025-05-06 16:24:56 +08:00
|
|
|
|
#region NoSql
|
|
|
|
|
if (this.Context.Ado is AdoProvider provider)
|
|
|
|
|
{
|
|
|
|
|
if (provider.IsNoSql)
|
|
|
|
|
{
|
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
|
|
|
|
if (method.IsVirtual)
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, method);
|
|
|
|
|
else
|
|
|
|
|
generator.Emit(OpCodes.Call, method);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
2017-07-09 19:12:41 +08:00
|
|
|
|
#region Sqlite Logic
|
|
|
|
|
if (this.Context.CurrentConnectionConfig.DbType == DbType.Sqlite)
|
|
|
|
|
{
|
2017-07-10 00:55:18 +08:00
|
|
|
|
if (bindPropertyType.IsEnum())
|
|
|
|
|
{
|
|
|
|
|
method = isNullableType ? getConvertEnum_Null.MakeGenericMethod(bindPropertyType) : getEnum.MakeGenericMethod(bindPropertyType);
|
|
|
|
|
}
|
2017-08-25 22:22:12 +08:00
|
|
|
|
else if (bindPropertyType == UtilConstants.IntType)
|
2017-07-09 21:11:32 +08:00
|
|
|
|
{
|
|
|
|
|
method = isNullableType ? getConvertInt32 : getInt32;
|
|
|
|
|
}
|
2022-10-27 13:36:43 +08:00
|
|
|
|
else if (bindPropertyType == UtilConstants.DateTimeOffsetType&&SugarCompatible.IsFramework)
|
2022-10-27 00:36:25 +08:00
|
|
|
|
{
|
|
|
|
|
method = isNullableType ? getConvertdatetimeoffset : getdatetimeoffset;
|
|
|
|
|
}
|
2019-04-20 20:26:21 +08:00
|
|
|
|
else if (bindPropertyType == UtilConstants.ByteType)
|
|
|
|
|
{
|
|
|
|
|
method = isNullableType ? getConvertByte : getByte;
|
|
|
|
|
}
|
2022-04-28 14:50:14 +08:00
|
|
|
|
else if (bindPropertyType == UtilConstants.StringType && dbTypeName?.ToLower() == "timestamp")
|
|
|
|
|
{
|
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
|
|
|
|
}
|
2023-03-03 22:48:50 +08:00
|
|
|
|
else if (dbTypeName.EqualCase("STRING"))
|
2020-11-02 11:06:56 +08:00
|
|
|
|
{
|
2021-02-04 21:47:14 +08:00
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
2020-11-02 11:06:56 +08:00
|
|
|
|
}
|
2023-05-12 22:30:24 +08:00
|
|
|
|
else if (bindPropertyType == UtilConstants.StringType&&validPropertyName == "int")
|
|
|
|
|
{
|
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
|
|
|
|
}
|
2017-08-25 22:22:12 +08:00
|
|
|
|
else if (bindPropertyType == UtilConstants.StringType)
|
2017-07-09 21:11:32 +08:00
|
|
|
|
{
|
|
|
|
|
method = getString;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-02-04 21:47:14 +08:00
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
2017-07-09 21:11:32 +08:00
|
|
|
|
}
|
2019-07-15 16:24:07 +08:00
|
|
|
|
if (method.IsVirtual)
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, method);
|
|
|
|
|
else
|
|
|
|
|
generator.Emit(OpCodes.Call, method);
|
2017-07-09 19:12:41 +08:00
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Common Database Logic
|
2017-06-07 02:12:04 +08:00
|
|
|
|
string bindProperyTypeName = bindPropertyType.Name.ToLower();
|
2017-07-01 13:10:36 +08:00
|
|
|
|
bool isEnum = bindPropertyType.IsEnum();
|
2017-06-07 02:12:04 +08:00
|
|
|
|
if (isEnum) { validPropertyType = CSharpDataType.@enum; }
|
|
|
|
|
switch (validPropertyType)
|
2017-01-07 21:54:51 +08:00
|
|
|
|
{
|
2017-06-07 02:12:04 +08:00
|
|
|
|
case CSharpDataType.@int:
|
|
|
|
|
CheckType(bind.IntThrow, bindProperyTypeName, validPropertyName, propertyName);
|
2017-07-11 22:06:05 +08:00
|
|
|
|
if (bindProperyTypeName.IsContainsIn("int", "int32"))
|
2017-06-09 18:55:45 +08:00
|
|
|
|
method = isNullableType ? getConvertInt32 : getInt32;
|
2017-07-11 22:06:05 +08:00
|
|
|
|
if (bindProperyTypeName.IsContainsIn("int64"))
|
2022-04-08 14:28:57 +08:00
|
|
|
|
method = null;
|
2017-07-17 12:24:29 +08:00
|
|
|
|
if (bindProperyTypeName.IsContainsIn("byte"))
|
|
|
|
|
method = isNullableType ? getConvertByte : getByte;
|
|
|
|
|
if (bindProperyTypeName.IsContainsIn("int16"))
|
|
|
|
|
method = isNullableType ? getConvertInt16 : getInt16;
|
2022-09-30 15:49:08 +08:00
|
|
|
|
if (bindProperyTypeName == "uint32"&&this.Context.CurrentConnectionConfig.DbType.IsIn(DbType.MySql,DbType.MySqlConnector))
|
|
|
|
|
method = null;
|
2024-05-09 10:37:57 +08:00
|
|
|
|
if (bindPropertyType ==UtilConstants.IntType&& this.Context.CurrentConnectionConfig.DbType == DbType.OceanBaseForOracle)
|
2024-05-08 18:27:23 +08:00
|
|
|
|
method = isNullableType ? getMyIntNull : getMyInt;
|
2025-03-28 16:51:27 +08:00
|
|
|
|
if (bindProperyTypeName == "int16")
|
|
|
|
|
method = null;
|
2017-06-07 02:12:04 +08:00
|
|
|
|
break;
|
|
|
|
|
case CSharpDataType.@bool:
|
|
|
|
|
if (bindProperyTypeName == "bool" || bindProperyTypeName == "boolean")
|
|
|
|
|
method = isNullableType ? getConvertBoolean : getBoolean;
|
|
|
|
|
break;
|
|
|
|
|
case CSharpDataType.@string:
|
2020-11-10 23:21:40 +08:00
|
|
|
|
if (this.Context.CurrentConnectionConfig.DbType != DbType.Oracle)
|
|
|
|
|
{
|
|
|
|
|
CheckType(bind.StringThrow, bindProperyTypeName, validPropertyName, propertyName);
|
|
|
|
|
}
|
2017-06-07 02:12:04 +08:00
|
|
|
|
method = getString;
|
2017-07-09 19:12:41 +08:00
|
|
|
|
if (bindProperyTypeName == "guid")
|
|
|
|
|
{
|
2017-10-10 14:41:08 +08:00
|
|
|
|
method = isNullableType ? getConvertStringGuid : getStringGuid;
|
2017-06-25 23:42:53 +08:00
|
|
|
|
}
|
2023-01-07 18:29:27 +08:00
|
|
|
|
else if (bindProperyTypeName == "xelement")
|
2022-05-14 17:23:35 +08:00
|
|
|
|
{
|
2023-01-07 18:29:27 +08:00
|
|
|
|
method = getXelement;
|
|
|
|
|
}
|
2023-01-09 20:43:45 +08:00
|
|
|
|
else if (dbTypeName == "CHAR" && DataRecord.GetDataTypeName(ordinal) == "CHAR(36)")
|
|
|
|
|
{
|
|
|
|
|
method = null;
|
|
|
|
|
}
|
|
|
|
|
else if (bindPropertyType.Name == "Char")
|
2023-01-07 18:29:27 +08:00
|
|
|
|
{
|
|
|
|
|
method = null;
|
2022-05-14 17:23:35 +08:00
|
|
|
|
}
|
2017-06-07 02:12:04 +08:00
|
|
|
|
break;
|
|
|
|
|
case CSharpDataType.DateTime:
|
|
|
|
|
CheckType(bind.DateThrow, bindProperyTypeName, validPropertyName, propertyName);
|
|
|
|
|
if (bindProperyTypeName == "datetime")
|
|
|
|
|
method = isNullableType ? getConvertDateTime : getDateTime;
|
2019-07-15 16:24:07 +08:00
|
|
|
|
if (bindProperyTypeName == "datetime" && dbTypeName.ToLower() == "time")
|
2018-04-08 16:31:27 +08:00
|
|
|
|
method = isNullableType ? getConvertTime : getTime;
|
2020-12-30 18:38:55 +08:00
|
|
|
|
if (bindProperyTypeName == "datetimeoffset")
|
|
|
|
|
method = isNullableType ? getConvertdatetimeoffset : getdatetimeoffset;
|
2017-06-07 02:12:04 +08:00
|
|
|
|
break;
|
|
|
|
|
case CSharpDataType.@decimal:
|
|
|
|
|
CheckType(bind.DecimalThrow, bindProperyTypeName, validPropertyName, propertyName);
|
|
|
|
|
if (bindProperyTypeName == "decimal")
|
|
|
|
|
method = isNullableType ? getConvertDecimal : getDecimal;
|
|
|
|
|
break;
|
2017-06-17 00:27:47 +08:00
|
|
|
|
case CSharpDataType.@float:
|
2017-06-07 02:12:04 +08:00
|
|
|
|
case CSharpDataType.@double:
|
|
|
|
|
CheckType(bind.DoubleThrow, bindProperyTypeName, validPropertyName, propertyName);
|
2019-07-15 16:24:07 +08:00
|
|
|
|
if (bindProperyTypeName.IsIn("double", "single") && dbTypeName != "real")
|
2017-06-07 02:12:04 +08:00
|
|
|
|
method = isNullableType ? getConvertDouble : getDouble;
|
2017-11-23 14:55:12 +08:00
|
|
|
|
else
|
|
|
|
|
method = isNullableType ? getConvertFloat : getFloat;
|
2019-07-15 16:24:07 +08:00
|
|
|
|
if (dbTypeName.Equals("float", StringComparison.CurrentCultureIgnoreCase) && isNullableType && bindProperyTypeName.Equals("single", StringComparison.CurrentCultureIgnoreCase))
|
|
|
|
|
{
|
2018-11-26 00:13:18 +08:00
|
|
|
|
method = getConvertDoubleToFloat;
|
|
|
|
|
}
|
2019-05-24 20:06:25 +08:00
|
|
|
|
if (bindPropertyType == UtilConstants.DecType)
|
|
|
|
|
{
|
2021-02-04 21:47:14 +08:00
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
2019-05-24 20:06:25 +08:00
|
|
|
|
}
|
2019-05-24 20:55:06 +08:00
|
|
|
|
if (bindPropertyType == UtilConstants.IntType)
|
|
|
|
|
{
|
2021-02-04 21:47:14 +08:00
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
2019-05-24 20:55:06 +08:00
|
|
|
|
}
|
2023-08-23 15:02:19 +08:00
|
|
|
|
if (bindProperyTypeName == "string")
|
|
|
|
|
{
|
|
|
|
|
method = null;
|
|
|
|
|
}
|
2017-06-07 02:12:04 +08:00
|
|
|
|
break;
|
|
|
|
|
case CSharpDataType.Guid:
|
|
|
|
|
CheckType(bind.GuidThrow, bindProperyTypeName, validPropertyName, propertyName);
|
|
|
|
|
if (bindProperyTypeName == "guid")
|
2017-09-07 19:46:15 +08:00
|
|
|
|
method = isNullableType ? getConvertGuid : getGuid;
|
2017-06-07 02:12:04 +08:00
|
|
|
|
break;
|
|
|
|
|
case CSharpDataType.@byte:
|
2017-07-25 13:54:01 +08:00
|
|
|
|
if (bindProperyTypeName == "byte")
|
|
|
|
|
method = isNullableType ? getConvertByte : getByte;
|
2017-06-07 02:12:04 +08:00
|
|
|
|
break;
|
|
|
|
|
case CSharpDataType.@enum:
|
|
|
|
|
method = isNullableType ? getConvertEnum_Null.MakeGenericMethod(bindPropertyType) : getEnum.MakeGenericMethod(bindPropertyType);
|
|
|
|
|
break;
|
|
|
|
|
case CSharpDataType.@short:
|
|
|
|
|
CheckType(bind.ShortThrow, bindProperyTypeName, validPropertyName, propertyName);
|
2017-06-25 05:33:39 +08:00
|
|
|
|
if (bindProperyTypeName == "int16" || bindProperyTypeName == "short")
|
2017-06-07 02:12:04 +08:00
|
|
|
|
method = isNullableType ? getConvertInt16 : getInt16;
|
|
|
|
|
break;
|
|
|
|
|
case CSharpDataType.@long:
|
2017-06-25 05:33:39 +08:00
|
|
|
|
if (bindProperyTypeName == "int64" || bindProperyTypeName == "long")
|
2017-07-11 22:06:05 +08:00
|
|
|
|
method = isNullableType ? getConvertInt64 : getInt64;
|
2017-06-07 02:12:04 +08:00
|
|
|
|
break;
|
2017-09-20 12:44:10 +08:00
|
|
|
|
case CSharpDataType.DateTimeOffset:
|
2017-10-10 14:41:08 +08:00
|
|
|
|
method = isNullableType ? getConvertdatetimeoffset : getdatetimeoffset;
|
2017-09-20 12:44:10 +08:00
|
|
|
|
if (bindProperyTypeName == "datetime")
|
|
|
|
|
method = isNullableType ? getConvertdatetimeoffsetDate : getdatetimeoffsetDate;
|
|
|
|
|
break;
|
2020-12-04 21:39:12 +08:00
|
|
|
|
case CSharpDataType.Single:
|
|
|
|
|
break;
|
2017-06-07 02:12:04 +08:00
|
|
|
|
default:
|
2021-02-04 21:47:14 +08:00
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
2017-06-07 02:12:04 +08:00
|
|
|
|
break;
|
2017-01-07 21:54:51 +08:00
|
|
|
|
}
|
2017-08-25 22:22:12 +08:00
|
|
|
|
if (method == null && bindPropertyType == UtilConstants.StringType)
|
2017-07-09 19:12:41 +08:00
|
|
|
|
{
|
2017-06-07 14:25:33 +08:00
|
|
|
|
method = getConvertString;
|
2017-06-07 13:46:45 +08:00
|
|
|
|
}
|
2017-10-10 14:41:08 +08:00
|
|
|
|
if (bindPropertyType == UtilConstants.ObjType)
|
|
|
|
|
{
|
2021-02-04 21:47:14 +08:00
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
2017-10-10 14:27:40 +08:00
|
|
|
|
}
|
2017-06-07 02:12:04 +08:00
|
|
|
|
if (method == null)
|
2017-07-09 19:12:41 +08:00
|
|
|
|
method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType);
|
2019-05-24 19:06:36 +08:00
|
|
|
|
|
2023-03-03 22:48:50 +08:00
|
|
|
|
|
2019-07-15 16:24:07 +08:00
|
|
|
|
if (method.IsVirtual)
|
|
|
|
|
generator.Emit(OpCodes.Callvirt, method);
|
|
|
|
|
else
|
|
|
|
|
generator.Emit(OpCodes.Call, method);
|
2017-07-09 19:12:41 +08:00
|
|
|
|
#endregion
|
2017-04-23 02:57:59 +08:00
|
|
|
|
}
|
2017-06-07 02:12:04 +08:00
|
|
|
|
|
2023-03-03 22:48:50 +08:00
|
|
|
|
|
2017-06-07 02:12:04 +08:00
|
|
|
|
private void CheckType(List<string> invalidTypes, string bindProperyTypeName, string validPropertyType, string propertyName)
|
2017-04-23 14:30:42 +08:00
|
|
|
|
{
|
2017-06-07 02:12:04 +08:00
|
|
|
|
var isAny = invalidTypes.Contains(bindProperyTypeName);
|
2017-04-23 14:30:42 +08:00
|
|
|
|
if (isAny)
|
|
|
|
|
{
|
2018-12-07 16:32:42 +08:00
|
|
|
|
throw new SqlSugarException(string.Format("{0} can't convert {1} to {2}", propertyName, validPropertyType, bindProperyTypeName));
|
2017-04-23 14:30:42 +08:00
|
|
|
|
}
|
2017-06-07 02:12:04 +08:00
|
|
|
|
}
|
2017-05-28 18:49:49 +08:00
|
|
|
|
#endregion
|
2025-06-26 10:38:58 +08:00
|
|
|
|
}
|
2017-01-07 21:54:51 +08:00
|
|
|
|
}
|