我能过C#对mysql数据库操作,其中数据操作方面有方法ExecuteNonQuery,表对应的实体类有Users、Department、rule等表。其中ExecuteNonQuery方法定义如下:
/// <summary>
/// 数据库增、删、改操作
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sql">sql语句</param>
/// <param name="obj">相关实体类</param>
/// <param name="classType">相关实体类类型</param>
/// <returns></returns>
public static int ExecuteNonQuery<T>(string sql, T obj, Type classType)
下面是添加Users记录的方法:
public int AddUsers(Users usersInfo)
        {
            string sql = "Insert into users(UserID,RoleName,Description)VALUES(@UserID,@RoleName,@Description)";
            //调用数据库操作类方法, 执行插入语句
            return MySqlHelper.ExecuteNonQuery(sql, usersInfo, typeof(Users));
        }
其它实体操作类中,也有类似与添加Users表方法,只是相关sql语句内容不同,第二个参数的实体以及第三个参数的类型不同。
————————————————————————————
下面是我的问题:
    我怎么利用一个ExecuteNonQuery方法处理不同表对应实体类的操作?
    这里我在ExecuteNonQuery的第二个参数用了泛型,我的意图是,在调用此方法时,反射得到相应的实体类,将实体类的数据动态的赋值给SQL语句中的参数。
请高手给予指点,最好有完整示例说明,本人将感激不尽。

解决方案 »

  1.   

    和泛型没有关系。第三个参数也没用。public static int ExecuteNonQuery<T>(string sql, T obj)
    {
        string propertites = string.Join(",", typeof(T).GetPropertites().Select(x => "@" + x.Name));
        string sql = "Insert into users(" + propertites.Replace("@", "") + ") VALUES(" + propertites + ")";
        ...
    }
      

  2.   

    反射
    T.GetType().GetProperty("属性名").GetValue,得到相关属性名,然后赋值给sql
      

  3.   

    注意这个代码只是演示,不能用于生产。实际上你的代码也不行,你应该用成熟的ORM。
      

  4.   

    可以给每个实体类与数据库对应的字段定义attribute...
      

  5.   


    与泛型无关?
    那如果我有三个表对应的实体类Users、Department、Rule,分别对应的数据操作为DBUsers、DBDepartment、DBRule类,对应的三个接口为:iIUsers、IDepartment、IRule。
         /// <summary>
        /// 用户信息操作类
         /// </summary>
        public interface IUsers
        {
            int AddUsers(Users usersInfo);
            void UpdateUser(Users usersInfo);
            int DelUsers(string userId);
            Users getUsersById(int userId);
            ArrayList getUsersByEname(string Ename);
            ……
        }    /// <summary>
        /// 部门信息操作类
         /// </summary>
        public interface IDepartment
        {
            int AddDepartment(Department departmentInfo);
            void UpdateDepartment(Department departmentInfo);
            int DelDepartment(string id);
            Department getDepartmentById(int id);
            ……
        }
        ……
    我在
    public class DBUsers : IUsers
    {
        #region IUsers 成员
         public int AddUsers(Users usersInfo)
        {
            string sql = "Insert into users(UserID,RoleName,Description)VALUES(@UserID,@RoleName,@Description)";
            //这里按你说的,把第三个参数去掉
            MySqlHelper.ExecuteNonQuery(sql, usersInfo);
        }
         #endregion
    }
    ------------------------------------------
            /// <summary>
            /// 数据库增、删、改操作
              /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="sql">sql语句</param>
            /// <param name="obj">相关实体类</param>
            /// <returns></returns>
            public static int ExecuteNonQuery<T>(string sql, T obj) 
            {
                int rInt = 0;
                MySqlCommand cmd = new MySqlCommand();
                MySqlConnection Conn = GetMySqlConnection();
                cmd.Connection = Conn;
                cmd.CommandText = sql;            //将泛型转换为classType给定的类型,并依次对Parameters赋值        
                  /*
                  此处就是我要针对传递来的实体类,依次向Parameters赋值。
                     如第二个参数为Users实体类
                  cmd.Parameters.Add("@U_LoginName", MySqlDbType.VarChar).Value = obj.LoginName;
                  cmd.Parameters.Add("@U_Password", MySqlDbType.VarChar).Value = obj.Password;
                  ……
                     但如果第二个参数即obj为Department实体类,则此处应自动辨别并进行赋值,如下:
                     cmd.Parameters.Add("@D_DepCode", MySqlDbType.VarChar).Value = obj.DepCode;
                  cmd.Parameters.Add("@D_DepName", MySqlDbType.VarChar).Value = obj.DepName;
                  也就是说,不可能在这里做无限的判断,应能自动根据传入的obj,并进行自动转换为对应的类型,根据sql中需要插入的字段进行自动分配赋值。对于各个表的操作类来说,对应的增、删、改,数据层提供的开放方法为:ExecuteNonQuery<T>(string sql, T obj)
                */
                
                Conn.Open();
                _tran = Conn.BeginTransaction();
                cmd.Transaction = _tran;
                try
                {
                    rInt = cmd.ExecuteNonQuery();
                    //MySql.Data.MySqlClient.MySqlHelper.ExecuteNonQuery(Conn, sql, parameters);
                    cmd.Parameters.Clear();
                    _tran.Commit();
                }
                catch (Exception ex)
                {
                    _tran.Rollback();
                    rInt = -1;
                    throw new ApplicationException(ex.ToString());
                }
                finally
                {
                    _tran.Dispose();
                    cmd.Dispose();
                    Conn.Dispose();
                    Conn.Close();
                }
                return rInt;
            }
    -----------------------------------
    以上就是我想实现的描述,不知大家是否对我的表达能够明白,如有能解决此方法的办法或思路,肯请尽可能详细的指点我。谢谢
      

  6.   

    首先要获取sql语句中的参数化变量,再反射读取对象属性值自动赋值(sql语句中的参数化变量要和对象的属性名称相同)
    上次在csdn问到的//获取所有sql参数化语句的变量名称,如@UserId 
    List<string> sqlParams = new List<string>();
    Regex reg = new Regex(@"(?<!@)[^\w$#@]@(?!@)[\w$#@]+");//可以区分select @@identity
    MatchCollection matches = reg.Matches(_command.CommandText);
    foreach (Match item in matches)
    {
        //正则取出来的数据会有=、(符号,如=@UserId或(@UserId
        sqlParams.Add(item.Groups[0].Value.Substring(item.Groups[0].Value.IndexOf("@")));
    }_command.Parameters.Clear();
    foreach (string param in sqlParams)
    {
        //param.Substring(1)将得到UserId
        object value = ObjectHelper.GetPropertyValueByPropertyName(param.Substring(1), data);
        _command.Parameters.AddWithValue(param, value);
    }
      

  7.   


    能具体说一下吗?
    我这样做的思路是,自已或别人再在前端写代码时,就简单多了,比如增加一个用户或客户关系等等表时,从页面拿到值并赋值后,很简单也很明了的就完成了数据库的操作,在前端如下代码:
    protected void btnSave_Click(object sender, EventArgs e)
            {
                Users userInfo = new Users();
                userInfo.UserName = txtUserName.Text.Trim();
                userInfo.Password = Common.md5(txtPWD.Text.Trim());
                userInfo.UserStatus = 0;
                ……
                   //实例化对应表的实体操作类
                IUsers users = UsersDAL.create();
                //增加一个新用户
                users.AddUsers(userInfo);
            }
    在其它前端,只是实体操作类和对应的数据不一样,但数据库操作都是统一的。
    请赐教!
      

  8.   

    最近写的数据库自动访问类,不过这种还是没有orm之类的框架好,还要自己写sql语句,效率的我也没有具体的测试,lz有些问题最好自己想一想,再google,百度,再不行就csdn
     public static object GetPropertyValueByPropertyName(string propertyName, object objectInstance)
            {
    PropertyInfo pi = objectInstance.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
                if (pi != null)
                {
                    if (pi.CanRead)
                    {
                        object value = pi.GetValue(objectInstance, null);
                        if (value == null)
                            value = DBNull.Value;
                        else if (pi.PropertyType.Name == typeof(DateTime).Name && Convert.ToDateTime(value) == DateTime.MinValue)
                            value = DBNull.Value;//防止数据库是smalldatetime类型时DateTime.MinValue溢出
                        return value;
                    }
                    else
                    {
                        throw new ArgumentException("自动设置参数值失败。对象的" + propertyName + "属性没有get方式,无法读取值。");
                    }
                }}
      

  9.   


    我baidu、google了很多,获得的知识不是很多,也许是我搜商不行吧。哎。
    自已写的肯定和成熟的ORM没法相比,我也想过拿开源的ORM代码读一下,但种种原因导致至少目前没有这个时间吧。还有自已亲自写一下,哪怕再垃圾,从中也能学到不少,我是这样认为的。
    我的SQL都写到了XML中,通过ID加载查询而得到相应的SQL语句,这样别人用的时候,就方便多了,也不用去动源码。