/// <summary>
    /// DataElement
    /// 数据对象类型的基础类 实现各个表通用操作方法
    /// </summary>
    public abstract class DataElement
    {
        /// <summary>
        /// 表名
        /// </summary>
        protected string _TableName;
        /// <summary>
        /// 主键值
        /// </summary>
        protected object _PrimaryKeyValue;
        public object PrimaryKeyValue
        {
            get { return _PrimaryKeyValue; }
        }        /// <summary>
        /// 主键列名
        /// </summary>
        protected string _PrimaryKey;        /// <summary>
        /// 数据库连接
        /// </summary>
        protected System.Data.SqlClient.SqlConnection conn;        /// <summary>
        /// 插入数据的sql字串 根据各个public并且可写的属性 使用反射来构造语句
        /// </summary>
        protected virtual string _InsertString
        {
            get
            {
                System.Reflection.PropertyInfo[] pis = this.GetType().GetProperties();
                string[] cols = new string[pis.Length];
                string[] vals = new string[pis.Length];
                int c = 0;
                foreach (System.Reflection.PropertyInfo pi in pis)
                {
                    if (pi.CanWrite)
                    {
                        cols[c] = String.Format("[{0}]", pi.Name);
                        vals[c] = String.Format("'{0}'", pi.GetValue(this, null));
                        c++;
                    }
                }
                return String.Format("INSERT INTO [{0}]({1})VALUES({2})"
                    , _TableName
                    , String.Join(",", cols, 0, c)
                    , String.Join(",", vals, 0, c)
                );
            }
        }        /// <summary>
        /// 更新数据的sql字符串
        /// </summary>
        protected virtual string _UpdateString
        {
            get
            {
                System.Reflection.PropertyInfo[] pis = this.GetType().GetProperties();
                string[] cols = new string[pis.Length];
                int c = 0;
                foreach (System.Reflection.PropertyInfo pi in pis)
                {
                    if (pi.CanWrite)
                    {
                        cols[c++] = String.Format("[{0}]='{1}'", pi.Name, pi.GetValue(this, null));
                    }
                }
                return String.Format("UPDATE [{0}] SET {1} WHERE [{2}]='{3}'"
                    , _TableName
                    , String.Join(",", cols, 0, c)
                    , _PrimaryKey
                    , _PrimaryKeyValue
                    );
            }
        }        /// <summary>
        /// 删除数据的字符串
        /// </summary>
        protected virtual string _DeleteString
        {
            get
            {
                return String.Format("DELETE FROM [{0}] WHERE [{1}]='{2}'", _TableName, _PrimaryKey, _PrimaryKeyValue);
            }
        }        /// <summary>
        /// 删除数据的方法
        /// </summary>
        public void Delete()
        {
            if (_PrimaryKeyValue == null) throw new Exception("未对主键赋值");
            DATAOP.Command(_DeleteString, conn);
        }        /// <summary>
        /// 保存数据的方法 根据主键值是否为空来判断应insert还是update
        /// </summary>
        public virtual void Save()
        {
            if (_PrimaryKeyValue == null)
                DATAOP.Command(_InsertString, conn);
            else
                DATAOP.Command(_UpdateString, conn);
        }        /// <summary>
        /// 调用数据的方法
        /// </summary>
        public virtual void Load()
        {
            if (_PrimaryKeyValue != null)
            {
                DataTable dt = DATAOP.DT(
                    String.Format("SELECT * FROM [{0}] WHERE [{1}]='{2}'", _TableName, _PrimaryKey, _PrimaryKeyValue)
                    , conn
                    );
                if (dt.Rows.Count > 0)
                {
                    Load(dt.Rows[0]);
                }
            }
        }        /// <summary>
        /// 根据数据行调用数据 调用多行时可用 不必多次开闭数据库连接
        /// </summary>
        /// <param name="row"></param>
        public void Load(DataRow row)
        {
            foreach (System.Reflection.PropertyInfo pi in this.GetType().GetProperties())
            {
                if (pi.CanWrite)
                {
                    if (row.Table.Columns[pi.Name] != null)
                    {
                        if (pi.PropertyType.ToString() == "System.Xml.XmlDocument")
                        {
                            System.Xml.XmlDocument xd = new System.Xml.XmlDocument();
                            xd.Load(row[pi.Name].ToString());
                            pi.SetValue(this, xd, null);
                        }
                        else
                        {
                            pi.SetValue(this, Convert.ChangeType(row[pi.Name], pi.PropertyType), null);
                        }
                    }
                }
            }
            _PrimaryKeyValue = row[_PrimaryKey];
        }
        /// <summary>
        /// 设置主键值
        /// </summary>
        /// <param name="value"></param>
        public void SetPrimaryKeyValue(object value) { _PrimaryKeyValue = value; }        /// <summary>
        /// 过滤非法字
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        protected virtual string StringFilter(string str) { return str == null ? null : str.Replace("'", "`"); }        /// <summary>
        /// 过滤非法字并限制字长
        /// </summary>
        /// <param name="str"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        protected virtual string StringFilter(string str, int len)
        {
            if (str == null) return null;
            str = str.Replace("'", "`");
            if (str.Length > len) str = str.Substring(0, len);
            return str;
        }        /// <summary>
        /// 反向还原字串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        protected string StringUnFilter(string str) { return str == null ? null : str.Replace("`", "'"); }
    }
主要的心得是insert和update字串通过反射的方式来生成。当然前提是单一的主键。一些简单的数据库操作应该是可以方便得多了。比如一个继承了该类的User类,添加用户的方式如下    void Button1_Click(object sender, EventArgs e)
    {
        MKCMS.User u = new MKCMS.User();
        u.Name = TextBox1.Text.Trim();
        u.Password = TextBox2.Text.Trim();
        u.Email = TextBox3.Text.Trim();
        u.Description = TextBox4.Text.Trim();
        u.Save();
    }
这样节省了大量的页面代码。希望代码对你有帮助,分数这方面实在囊中羞涩了。

解决方案 »

  1.   

    忘记了一件事情。那个User的例子已经重写了Save方法,所以例子中没有配置conn        /// <summary>
            /// 重写保存方法 内置了数据库连接
            /// </summary>
            public override void Save()
            {
                if (!CheckName) throw new Exception("已存在此用户名");
                else
                {
                    MSSQL sql = new MSSQL();
                    sql.Open();
                    conn = sql.Connection;
                    base.Save();
                    sql.Close();
                    sql.Dispose();
                }
            }这个MSSQL是我上一贴中的数据库连接类,就不再详细叙述了。
      

  2.   

    可以考虑将System.data.SqlClient.SqlConnection改为System.Data.IDbConnection,以便可以考虑支持其它类型的数据