Esempio n. 1
0
        /// <summary>
        /// Retrieve a single record from a DB table. Any subsequent rows are ignored.
        /// Will throw formatted exception upon error.
        /// Note: field/property name must be the same as the database column name (case-insensitive).
        /// </summary>
        /// <typeparam name="T">Typeof class object to return.</typeparam>
        /// <param name="connectionString"></param>
        /// <param name="query">parameterized query format string (see string.Format()) or stored procedure</param>
        /// <param name="args">format replacement args or stored procedure parameters</param>
        /// <returns>Typed class containing the retrieved results. null valuetype values get converted into their associated default value (aka Int32 type == 0, strings == "")</returns>
        public static T ExecuteQuerySingleRow <T>(string connectionString, string query, params object[] args) where T : class, new()
        {
            SqlCommand    cmd    = null;
            SqlDataReader reader = null;

            try
            {
                cmd    = CreateSqlCmd(connectionString, query, args);
                reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
                var fields = FieldProp.GetProperties(reader, typeof(T), STRICT);
                if (reader.Read())
                {
                    T item = new T();
                    for (int i = 0; i < fields.Length; i++)
                    {
                        if (fields[i].Type == null)
                        {
                            continue;                         //matching field not in query
                        }
                        fields[i].SetValue(item, ConvertTo(fields[i].Type, reader.GetValue(i)));
                    }
                    return(item);
                }
            }
            catch (Exception ex)
            {
                throw ex.AppendMessage(string.Format("ExecuteQuerySingleRow<{0}>(\"{1}\",\"{2}\",{{{3}}})", typeof(T).Name, HideCSPwd(connectionString), (query ?? string.Empty).Trim(), ParamsToString(args)));
            }
            finally
            {
                if (reader != null)
                {
                    reader.Dispose();
                }
                if (cmd != null)
                {
                    cmd.Dispose();
                }
            }
            return(null);
        }
Esempio n. 2
0
            private static FieldProp[] InternalGetPropertiesForgiving(IDataReader reader, Type t)
            {
                //Create a clean and smaller memberinfo search list.
                var members = new Dictionary <string, MemberInfo>(StringComparer.InvariantCultureIgnoreCase);

                foreach (var m in t.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                {
                    if (m.MemberType == MemberTypes.Field || m.MemberType == MemberTypes.Property)
                    {
                        string name = m.Attribute <ColumnAttribute>();
                        if (!name.IsNullOrEmpty())
                        {
                            members[name] = m;
                        }

                        members[m.Name] = m;
                    }
                }

                FieldProp[] fields = new FieldProp[reader.FieldCount];
                for (int i = 0; i < fields.Length; i++)
                {
                    string     name = reader.GetName(i);
                    MemberInfo mi   = null;
                    members.TryGetValue(name, out mi);
                    if (mi == null)
                    {
                        continue;
                    }

                    fields[i].Name = name;
                    if (mi.MemberType == MemberTypes.Field)
                    {
                        FieldInfo fi = (FieldInfo)mi;
                        fields[i].Type     = fi.FieldType;
                        fields[i].GetValue = fi.GetValue;
                        fields[i].SetValue = fi.SetValue;
                    }
                    else
                    {
                        PropertyInfo pi = (PropertyInfo)mi;
                        fields[i].Type = pi.PropertyType;
                        if (pi.CanRead)
                        {
                            fields[i].GetValue = pi.GetValue;
                        }
                        else
                        {
                            fields[i].GetValue = delegate(object obj) { return(ConvertTo(pi.PropertyType, null)); };
                        }

                        if (pi.CanWrite)
                        {
                            fields[i].SetValue = pi.SetValue;
                        }
                        else
                        {
                            fields[i].SetValue = delegate(object obj, object value) { };
                        }
                    }
                }

                return(fields);
            }
Esempio n. 3
0
            /// <summary>
            /// Strict like EF. Data model properties must match the Sql query column properties exactly.
            /// Data model properties may have the [NotMapped] or [Column("queryColumnName")] attributes
            /// to match the EF logic.
            /// </summary>
            /// <param name="reader">Datareader to read properties from</param>
            /// <param name="t">NET Type to read into</param>
            /// <returns>Array of class member properties that match IDataReader fields</returns>
            private static                                                            FieldProp[] InternalGetPropertiesStrict(IDataReader reader, Type t)
            {
                List <string> orphanedQueryColumns = null;
                List <string> typeMismatch         = null;

                //Create a clean and smaller memberinfo search list.
                var members = new Dictionary <string, PropertyInfo>(StringComparer.InvariantCulture);

                foreach (var m in t.GetProperties().Where(x => x.CanRead && x.CanWrite))
                {
                    var name = m.Attribute <NotMappedAttribute>();
                    if (name != null)
                    {
                        continue;
                    }

                    name = m.Attribute <ColumnAttribute>();
                    members[!name.IsNullOrEmpty() ? name : m.Name] = m;
                }

                FieldProp[] fields = new FieldProp[reader.FieldCount];
                for (int i = 0; i < fields.Length; i++)
                {
                    string       name = reader.GetName(i);
                    PropertyInfo pi   = null;
                    members.TryGetValue(name, out pi);

                    //Matching property does not exist for query column
                    if (pi == null)
                    {
                        if (orphanedQueryColumns == null)
                        {
                            orphanedQueryColumns = new List <string>();
                        }

                        orphanedQueryColumns.Add(name);
                        continue;
                    }

                    //Property type does not match query column type
                    var tt = pi.PropertyType;
                    if (tt.IsGenericType && tt.GetGenericTypeDefinition() == typeof(System.Nullable <>) && tt.GenericTypeArguments.Length > 0)
                    {
                        tt = tt.GenericTypeArguments[0];
                    }

                    if (reader.GetFieldType(i) != tt)
                    {
                        if (typeMismatch == null)
                        {
                            typeMismatch = new List <string>();
                        }

                        typeMismatch.Add(name);
                        members.Remove(name);
                        continue;
                    }

                    //Property and query column match!
                    fields[i].Name     = name;
                    fields[i].Type     = pi.PropertyType; //leave as nullable type so ConvertTo() knows how to handle it properly.
                    fields[i].GetValue = pi.GetValue;
                    fields[i].SetValue = pi.SetValue;
                    members.Remove(name);
                }

                //Get bad columns from strict matching. Format nice message and throw

                StringBuilder sb = null;

                if (orphanedQueryColumns != null)
                {
                    sb = new StringBuilder();
                    sb.Append("Query columns: ");
                    sb.Append(string.Join(", ", orphanedQueryColumns));
                    sb.Append(", do not have a matching case-sensitive, read/writeable '");
                    sb.Append(t.Name);
                    sb.Append("' properties.");
                }

                if (typeMismatch != null)
                {
                    if (sb == null)
                    {
                        sb = new StringBuilder();
                    }
                    else
                    {
                        sb.AppendLine();
                    }

                    sb.Append("Data model '");
                    sb.Append(t.Name);
                    sb.Append("' properties: ");
                    sb.Append(string.Join(", ", typeMismatch));
                    sb.Append(", do not have the same value type as the matching Sql query columns.");
                }

                if (members.Count > 0)
                {
                    if (sb == null)
                    {
                        sb = new StringBuilder();
                    }
                    else
                    {
                        sb.AppendLine();
                    }

                    sb.Append("Data model '");
                    sb.Append(t.Name);
                    sb.Append("' case-sensitive properties: ");
                    sb.Append(string.Join(", ", members.Keys.ToArray()));
                    sb.Append(", do not exist in the Sql query column headings.");
                }

                if (sb != null)
                {
                    throw new MissingMemberException(sb.ToString());
                }

                return(fields);
            }
Esempio n. 4
0
        /// <summary>
        /// Retrieve a table of data from a Sql query statement.
        /// Will throw formatted exception upon error.
        /// Note: field/property name must be the same as the database column name (case-insensitive).
        /// </summary>
        /// <typeparam name="T">
        ///   Typeof array element. If the array element is a primitive type, DateTime, or Guid
        ///   but not string, only the first column in the query is used. String does not have a
        ///   default constructor!
        /// </typeparam>
        /// <param name="connectionString"></param>
        /// <param name="query">parameterized query format string (see string.Format()) or stored procedure</param>
        /// <param name="args">format replacement args or stored procedure parameters</param>
        /// <returns>Generic list of typed class objects containing the retrieved results. null valuetype values get converted into their associated default value (aka Int32 type == 0, strings == "")</returns>
        public static List <T> ExecuteQuery <T>(string connectionString, string query, params object[] args)
        {
            SqlCommand    cmd    = null;
            SqlDataReader reader = null;
            List <T>      list   = new List <T>();
            Type          t      = typeof(T);

            //Is the return type a simple list of values?
            bool isPrimitive = t.IsPrimitive || t == typeof(string) || t == typeof(Guid) || t == typeof(Enum);

            try
            {
                cmd    = CreateSqlCmd(connectionString, query, args);
                reader = cmd.ExecuteReader(CommandBehavior.SingleResult);
                if (isPrimitive)
                {
                    while (reader.Read())
                    {
                        list.Add((T)ConvertTo(t, reader.GetValue(0))); //we ignore all the rest of the columns.
                    }

                    return(list);
                }

                var fields = FieldProp.GetProperties(reader, typeof(T), STRICT);

                //Find typeparam parameterless instance constructor. It may be public or private.
                var ci = t.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
                var constructorArgs = new object[] { }; //for efficiency

                while (reader.Read())
                {
                    var item = (T)ci.Invoke(constructorArgs);
                    for (int i = 0; i < fields.Length; i++)
                    {
                        if (fields[i].Type == null)
                        {
                            continue;                         //matching field not in query
                        }
                        fields[i].SetValue(item, ConvertTo(fields[i].Type, reader.GetValue(i)));
                    }
                    list.Add(item);
                }
            }
            catch (Exception ex)
            {
                throw ex.AppendMessage(string.Format("ExecuteQuery<{0}>(\"{1}\",\"{2}\",{{{3}}})", typeof(T).Name, HideCSPwd(connectionString), QueryForException(query), ParamsToString(args)));
            }
            finally
            {
                if (reader != null)
                {
                    reader.Dispose();
                }
                if (cmd != null)
                {
                    cmd.Dispose();
                }
            }
            return(list);
        }