public virtual StandardMapper Path(string path) { var mapper = new StandardMapper().Path(path); AddMapper(mapper); return(mapper); }
public PocoData(Type type, StandardMapper defaultMapper) { Type = type; // Get the mapper for this type var mapper = Mappers.GetMapper(type, defaultMapper); // Get the table info TableInfo = mapper.GetTableInfo(type); // Work out bound properties Columns = new Dictionary <string, PocoColumn>(StringComparer.OrdinalIgnoreCase); foreach (var pi in type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) { ColumnInfo ci = mapper.GetColumnInfo(pi); if (ci == null) { continue; } var pc = new PocoColumn(); pc.PropertyInfo = pi; pc.ColumnName = ci.ColumnName; pc.ResultColumn = ci.ResultColumn; pc.ForceToUtc = ci.ForceToUtc; pc.ResultSql = ci.ResultSql; // Store it Columns.Add(pc.ColumnName, pc); } // Build column list for automatic select QueryColumns = (from c in Columns where !c.Value.ResultColumn select c.Key).ToArray(); }
public static PocoData ForObject(object obj, string primaryKeyName, StandardMapper defaultMapper) { var t = obj.GetType(); if (t == typeof(System.Dynamic.ExpandoObject)) { var pd = new PocoData(); pd.TableInfo = new TableInfo(); pd.Columns = new Dictionary <string, PocoColumn>(StringComparer.OrdinalIgnoreCase); pd.Columns.Add(primaryKeyName, new ExpandoColumn() { ColumnName = primaryKeyName }); pd.TableInfo.PrimaryKey = primaryKeyName; pd.TableInfo.AutoIncrement = true; foreach (var col in (obj as IDictionary <string, object>).Keys) { if (col != primaryKeyName) { pd.Columns.Add(col, new ExpandoColumn() { ColumnName = col }); } } return(pd); } return(ForType(t, defaultMapper)); }
private static Func <object, object> GetConverter(StandardMapper mapper, PocoColumn pc, Type srcType, Type dstType) { Func <object, object> converter = null; // Get converter from the mapper if (pc != null) { converter = mapper.GetFromDbConverter(pc.PropertyInfo, srcType); if (converter != null) { return(converter); } } // Standard DateTime->Utc mapper if (pc != null && pc.ForceToUtc && srcType == typeof(DateTime) && (dstType == typeof(DateTime) || dstType == typeof(DateTime?))) { return(delegate(object src) { return new DateTime(((DateTime)src).Ticks, DateTimeKind.Utc); }); } // unwrap nullable types Type underlyingDstType = Nullable.GetUnderlyingType(dstType); if (underlyingDstType != null) { dstType = underlyingDstType; } // Forced type conversion including integral types -> enum if (dstType.IsEnum && IsIntegralType(srcType)) { var backingDstType = Enum.GetUnderlyingType(dstType); if (underlyingDstType != null) { // if dstType is Nullable<Enum>, convert to enum value return(delegate(object src) { return Enum.ToObject(dstType, src); }); } else if (srcType != backingDstType) { return(delegate(object src) { return Convert.ChangeType(src, backingDstType, null); }); } } else if (!dstType.IsAssignableFrom(srcType)) { if (dstType.IsEnum && srcType == typeof(string)) { return(delegate(object src) { return EnumMapper.EnumFromString(dstType, (string)src); }); } else if (dstType == typeof(Guid) && srcType == typeof(string)) { return(delegate(object src) { return Guid.Parse((string)src); }); } else { return(delegate(object src) { return Convert.ChangeType(src, dstType, null); }); } } return(null); }
public static PocoData ForType(Type type, StandardMapper defaultMapper = null) { if (type == typeof(System.Dynamic.ExpandoObject)) { throw new InvalidOperationException("Can't use dynamic types with this method"); } return(_pocoDatas.Get(type, () => new PocoData(type, defaultMapper))); }
public void Map_Returns_Valid_Model() { var model = new API.Models.StandardModel { StandardCode = "547", StandardName = "Broadcast and Media Systems Technician", StandardSectorCode = "11", StandardSectorCodeDesc2 = "Newspaper and Broadcast Media", Version = 1, NotionalEndLevel = "5", EffectiveFrom = new DateTime(2020, 03, 06), EffectiveTo = new DateTime(2022, 1, 1), LastDateStarts = new DateTime(2021, 1, 1), SectorSubjectAreaTier1 = "4", SectorSubjectAreaTier1Desc = "Engineering and Manufacturing Technolgies", SectorSubjectAreaTier2 = "4.10", SectorSubjectAreaTier2Desc = "Engineering", IntegratedDegreeStandard = "Y", OtherBodyApprovalRequired = "N" }; var mapper = new StandardMapper(); var result = mapper.Map(model); result.StandardCode.Should().Be(model.StandardCode); result.StandardName.Should().Be(model.StandardName); result.StandardSectorCode.Should().Be(model.StandardSectorCode); result.StandardSectorCodeDesc2.Should().Be(model.StandardSectorCodeDesc2); result.Version.Should().Be(model.Version); result.EffectiveFrom.Should().Be(model.EffectiveFrom); result.EffectiveTo.Should().Be(model.EffectiveTo); result.NotionalEndLevel.Should().Be(model.NotionalEndLevel); result.LastDateStarts.Should().Be(model.LastDateStarts); result.SectorSubjectAreaTier1.Should().Be(model.SectorSubjectAreaTier1); result.SectorSubjectAreaTier1Desc.Should().Be(model.SectorSubjectAreaTier1Desc); result.SectorSubjectAreaTier2.Should().Be(model.SectorSubjectAreaTier2); result.SectorSubjectAreaTier2Desc.Should().Be(model.SectorSubjectAreaTier2Desc); result.IntegratedDegreeStandard.Should().Be(model.IntegratedDegreeStandard); result.OtherBodyApprovalRequired.Should().Be(model.OtherBodyApprovalRequired); }
// Create factory function that can convert a IDataReader record into a POCO public Delegate GetFactory(string sql, string connectionString, int firstColumn, int countColumns, IDataReader reader, StandardMapper defaultMapper) { #region 创建Key SortedSet <string> list = new SortedSet <string>(); for (int i = 0; i < countColumns; i++) { list.Add(reader.GetName(i)); } list.Add(Type.FullName); StringBuilder sb = new StringBuilder(); foreach (var item in list) { sb.Append(item); sb.Append("|"); } var key = sb.ToString(); #endregion 创建Key return(PocoFactories.Get(key, () => { // Create the method var m = new DynamicMethod("tg_readygo_" + PocoFactories.Count.ToString(), Type, new Type[] { typeof(IDataReader) }, true); var il = m.GetILGenerator(); var mapper = Mappers.GetMapper(Type, defaultMapper); if (Type == typeof(object)) { // var poco=new T() il.Emit(OpCodes.Newobj, typeof(System.Dynamic.ExpandoObject).GetConstructor(Type.EmptyTypes)); // obj MethodInfo fnAdd = typeof(IDictionary <string, object>).GetMethod("Add"); // Enumerate all fields generating a set assignment for the column for (int i = firstColumn; i < firstColumn + countColumns; i++) { var srcType = reader.GetFieldType(i); il.Emit(OpCodes.Dup); // obj, obj il.Emit(OpCodes.Ldstr, reader.GetName(i)); // obj, obj, fieldname // Get the converter Func <object, object> converter = mapper.GetFromDbConverter((PropertyInfo)null, srcType); /* * if (ForceDateTimesToUtc && converter == null && srcType == typeof(DateTime)) * converter = delegate(object src) { return new DateTime(((DateTime)src).Ticks, DateTimeKind.Utc); }; */ // Setup stack for call to converter AddConverterToStack(il, converter); // r[i] il.Emit(OpCodes.Ldarg_0); // obj, obj, fieldname, converter?, rdr il.Emit(OpCodes.Ldc_I4, i); // obj, obj, fieldname, converter?, rdr,i il.Emit(OpCodes.Callvirt, fnGetValue); // obj, obj, fieldname, converter?, value // Convert DBNull to null il.Emit(OpCodes.Dup); // obj, obj, fieldname, converter?, value, value il.Emit(OpCodes.Isinst, typeof(DBNull)); // obj, obj, fieldname, converter?, value, (value or null) var lblNotNull = il.DefineLabel(); il.Emit(OpCodes.Brfalse_S, lblNotNull); // obj, obj, fieldname, converter?, value il.Emit(OpCodes.Pop); // obj, obj, fieldname, converter? if (converter != null) { il.Emit(OpCodes.Pop); // obj, obj, fieldname, } il.Emit(OpCodes.Ldnull); // obj, obj, fieldname, null if (converter != null) { var lblReady = il.DefineLabel(); il.Emit(OpCodes.Br_S, lblReady); il.MarkLabel(lblNotNull); il.Emit(OpCodes.Callvirt, fnInvoke); il.MarkLabel(lblReady); } else { il.MarkLabel(lblNotNull); } il.Emit(OpCodes.Callvirt, fnAdd); } } else if (Type.IsValueType || Type == typeof(string) || Type == typeof(byte[])) { // Do we need to install a converter? var srcType = reader.GetFieldType(0); var converter = GetConverter(mapper, null, srcType, Type); // "if (!rdr.IsDBNull(i))" il.Emit(OpCodes.Ldarg_0); // rdr il.Emit(OpCodes.Ldc_I4_0); // rdr,0 il.Emit(OpCodes.Callvirt, fnIsDBNull); // bool var lblCont = il.DefineLabel(); il.Emit(OpCodes.Brfalse_S, lblCont); il.Emit(OpCodes.Ldnull); // null var lblFin = il.DefineLabel(); il.Emit(OpCodes.Br_S, lblFin); il.MarkLabel(lblCont); // Setup stack for call to converter AddConverterToStack(il, converter); il.Emit(OpCodes.Ldarg_0); // rdr il.Emit(OpCodes.Ldc_I4_0); // rdr,0 il.Emit(OpCodes.Callvirt, fnGetValue); // value // Call the converter if (converter != null) { il.Emit(OpCodes.Callvirt, fnInvoke); } il.MarkLabel(lblFin); il.Emit(OpCodes.Unbox_Any, Type); // value converted } else { // var poco=new T() var ctor = Type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null); if (ctor == null) { throw new InvalidOperationException("Type [" + Type.FullName + "] should have default public or non-public constructor"); } il.Emit(OpCodes.Newobj, ctor); // Enumerate all fields generating a set assignment for the column for (int i = firstColumn; i < firstColumn + countColumns; i++) { // Get the PocoColumn for this db column, ignore if not known PocoColumn pc; if (!Columns.TryGetValue(reader.GetName(i), out pc)) { continue; } // Get the source type for this column var srcType = reader.GetFieldType(i); var dstType = pc.PropertyInfo.PropertyType; // "if (!rdr.IsDBNull(i))" il.Emit(OpCodes.Ldarg_0); // poco,rdr il.Emit(OpCodes.Ldc_I4, i); // poco,rdr,i il.Emit(OpCodes.Callvirt, fnIsDBNull); // poco,bool var lblNext = il.DefineLabel(); il.Emit(OpCodes.Brtrue_S, lblNext); // poco il.Emit(OpCodes.Dup); // poco,poco // Do we need to install a converter? var converter = GetConverter(mapper, pc, srcType, dstType); // Fast bool Handled = false; if (converter == null) { var valuegetter = typeof(IDataRecord).GetMethod("Get" + srcType.Name, new Type[] { typeof(int) }); if (valuegetter != null && valuegetter.ReturnType == srcType && (valuegetter.ReturnType == dstType || valuegetter.ReturnType == Nullable.GetUnderlyingType(dstType))) { il.Emit(OpCodes.Ldarg_0); // *,rdr il.Emit(OpCodes.Ldc_I4, i); // *,rdr,i il.Emit(OpCodes.Callvirt, valuegetter); // *,value // Convert to Nullable if (Nullable.GetUnderlyingType(dstType) != null) { il.Emit(OpCodes.Newobj, dstType.GetConstructor(new Type[] { Nullable.GetUnderlyingType(dstType) })); } il.Emit(OpCodes.Callvirt, pc.PropertyInfo.GetSetMethod(true)); // poco Handled = true; } } // Not so fast if (!Handled) { // Setup stack for call to converter AddConverterToStack(il, converter); // "value = rdr.GetValue(i)" il.Emit(OpCodes.Ldarg_0); // *,rdr il.Emit(OpCodes.Ldc_I4, i); // *,rdr,i il.Emit(OpCodes.Callvirt, fnGetValue); // *,value // Call the converter if (converter != null) { il.Emit(OpCodes.Callvirt, fnInvoke); } // Assign it il.Emit(OpCodes.Unbox_Any, pc.PropertyInfo.PropertyType); // poco,poco,value il.Emit(OpCodes.Callvirt, pc.PropertyInfo.GetSetMethod(true)); // poco } il.MarkLabel(lblNext); } var fnOnLoaded = RecurseInheritedTypes <MethodInfo>(Type, (x) => x.GetMethod("OnLoaded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null)); if (fnOnLoaded != null) { il.Emit(OpCodes.Dup); il.Emit(OpCodes.Callvirt, fnOnLoaded); } } il.Emit(OpCodes.Ret); // Cache it, return it return m.CreateDelegate(Expression.GetFuncType(typeof(IDataReader), Type)); } )); }
public static string AddSelectClause <T>(DatabaseProvider provider, string sql, StandardMapper defaultMapper) { sql = sql.Trim(); if (sql.StartsWith(";")) { return(sql.Substring(1)); } if (!rxSelect.IsMatch(sql)) { var pd = PocoData.ForType(typeof(T), defaultMapper); var tableName = provider.EscapeTableName(pd.TableInfo.TableName); StringBuilder stringBuilder = new StringBuilder(); foreach (var item in pd.Columns) { var col = item.Value; stringBuilder.Append(","); if (col.ResultColumn) { if (string.IsNullOrEmpty(col.ResultSql) == false) { stringBuilder.AppendFormat(col.ResultSql, tableName + "."); stringBuilder.Append(" AS "); stringBuilder.Append(col.ColumnName); } } else { stringBuilder.AppendFormat("{0}.{1}", tableName, provider.EscapeSqlIdentifier(col.ColumnName)); } } if (stringBuilder.Length == 0) { throw new NoColumnException(); } stringBuilder.Remove(0, 1); if (!rxFrom.IsMatch(sql)) { sql = string.Format("SELECT {0} FROM {1} {2}", stringBuilder.ToString(), tableName, sql); } else { sql = string.Format("SELECT {0} {1}", stringBuilder.ToString(), sql); } } return(sql); }