我能过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语句中的参数。
请高手给予指点,最好有完整示例说明,本人将感激不尽。
/// <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语句中的参数。
请高手给予指点,最好有完整示例说明,本人将感激不尽。
{
string propertites = string.Join(",", typeof(T).GetPropertites().Select(x => "@" + x.Name));
string sql = "Insert into users(" + propertites.Replace("@", "") + ") VALUES(" + propertites + ")";
...
}
T.GetType().GetProperty("属性名").GetValue,得到相关属性名,然后赋值给sql
与泛型无关?
那如果我有三个表对应的实体类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;
}
-----------------------------------
以上就是我想实现的描述,不知大家是否对我的表达能够明白,如有能解决此方法的办法或思路,肯请尽可能详细的指点我。谢谢
上次在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);
}
能具体说一下吗?
我这样做的思路是,自已或别人再在前端写代码时,就简单多了,比如增加一个用户或客户关系等等表时,从页面拿到值并赋值后,很简单也很明了的就完成了数据库的操作,在前端如下代码:
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);
}
在其它前端,只是实体操作类和对应的数据不一样,但数据库操作都是统一的。
请赐教!
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方式,无法读取值。");
}
}}
我baidu、google了很多,获得的知识不是很多,也许是我搜商不行吧。哎。
自已写的肯定和成熟的ORM没法相比,我也想过拿开源的ORM代码读一下,但种种原因导致至少目前没有这个时间吧。还有自已亲自写一下,哪怕再垃圾,从中也能学到不少,我是这样认为的。
我的SQL都写到了XML中,通过ID加载查询而得到相应的SQL语句,这样别人用的时候,就方便多了,也不用去动源码。