Example #1
0
        public virtual StandardMapper Path(string path)
        {
            var mapper = new StandardMapper().Path(path);

            AddMapper(mapper);
            return(mapper);
        }
Example #2
0
        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();
        }
Example #3
0
        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));
        }
Example #4
0
        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);
        }
Example #5
0
        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)));
        }
Example #6
0
        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);
        }
Example #7
0
        // 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);
        }