|
上面的方法大家看了是不是觉得既简单又熟悉,确实是的,但仍然相当以前的xxhelper.cs里是做了简化的,该方法既可以直接执行不带参DML语句,也可以执行带参的,但是该方法的形参却只有一个,之前的xxhelper.cs里带参执行的话,形参中大多至少还另外一个形参的,比如SqlPeremeters[]类型或参数集合类型的形参,而且方法体里面大多会循环读取参数,上面的方法里却没有,都简化掉了,唯一多了一点的是,所执行的命令语句执行前要做一个特殊字符替换,cmd.CommandText = Replace(Sql),Replace方法主要是替换参数前缀,Replace方法如下: /// <summary>
/// 替换DML语句里的参数前缀 /// </summary> /// <param name="str"></param> /// <returns></returns> public string Replace(string str) { return str.Replace("$", retParaformat.Substring(0, 1)); } 因为不同数据库除了在添加参数时有前缀的区别,再具体执行语句时也有前缀区别嘛,比如SQL SERVER里 SELECT USER_NAME,USER_AGE FROM USERS WHERE USER_ID=@USER_ID,ORACLE里是这样的SELECT USER_NAME,USER_AGE FROM USERS WHEREUSER_ID=:USER_ID,在此就需要统一一个前缀规则了,统一这样SELECT USER_NAME,USER_AGE FROM USERS WHERE USER_ID=$USER_ID,在执行前根据不同数据库替换前缀$符号,当然这个约定规则不一定是最完美的,也许还存在一定的问题,写到这我也突然想起来之前我见过别人的系统中有的就是变量参数用的这种类似特殊符号,肯定也是为了兼容多数据库所作的处理了,呵呵,具体的调用及测试之后统一说明。还有几个方法也和上面类似,大家都熟悉的。如下(不再做具体解释了): /// <summary> /// 执行SQL语句并返回DataReader对象 /// </summary> /// <param name="dbcon"></param> /// <param name="cmdText"></param> /// <returns></returns> public DbDataReader ExecuteDataReader(DbConnection dbcon,string cmdText) { try { if (dbcon.State == ConnectionState.Closed) { dbcon.Open(); } cmd.CommandText = Replace(cmdText); DbDataReader dr = cmd.ExecuteReader(); cmd.Parameters.Clear(); cmd.Dispose(); return dr; } catch { dbcon.Close();//发生异常在此处关闭,否则在调用显式处关闭 return null; } } /// <summary> /// 判断记录是否存在 /// </summary> /// <param name="Sql"></param> /// <returns></returns> public bool Exist(string Sql) { bool exist; this.Open(); cmd.CommandText = Replace(Sql); DbDataReader dr = cmd.ExecuteReader(); if (dr.HasRows) { exist = true; //记录存在 } else { exist = false; //记录不存在 } dr.Close(); this.Close(); return exist; } /// <summary> /// 执行SQL语句 /// </summary> /// <param name="sql"></param> public void ExecSql(string Sql) { try { this.Open(); cmd.CommandText = Replace(Sql); cmd.ExecuteNonQuery(); cmd.Dispose(); } catch (Exception ex) { throw ex; } finally { this.Close(); } } /// <summary> /// 执行SQL语句,返回一个单值 /// </summary> /// <param name="sql"></param> /// <returns></returns> public string ReturnValue(string Sql) { object returnValue = string.Empty; try { this.Open(); cmd.CommandText = Replace(Sql); returnValue = cmd.ExecuteScalar(); if (returnValue == null) { returnValue = string.Empty; } } catch (Exception ex) { throw ex; } finally { this.Close(); } return returnValue.ToString(); } /// <summary> /// 执行多条SQL语句并启用数据库事务 /// </summary> /// <param name="SQLStringList"></param> public bool ExecSqlTran(List<String> SQLStringList) { this.Open(); DbTransaction trans = conn.BeginTransaction(); cmd.Transaction = trans; try { for (int n = 0; n < SQLStringList.Count; n++) { cmd.CommandText = Replace(SQLStringList[n]); cmd.ExecuteNonQuery(); } trans.Commit(); return true; } catch { trans.Rollback(); return false; } finally { this.Close(); } } 下面说下两个存储过程,存储过程基本上分两种,返回结果集的存储过程和执行业务逻辑不返回结果集但却有返回值(如标志等),对于需要有返回值的存储过程,我个人趋向于用输出参数代替返回值,因为都能达到一样的效果目的,而且输出参数可以有多个,也就可以根据需要能有多个所谓的“返回值”,所以我之前的开发中一直是用output参数来代替return参数。 /// <summary> /// 执行存储过程并返回结果集 /// </summary> /// <param name="storedProcName">存储过程名</param> /// <returns>DataSet</returns> public DataSet RunProcedure(string storedProcName) { DataSet ds = new DataSet(); try { this.Open(); cmd.CommandText = storedProcName; cmd.CommandType = CommandType.StoredProcedure; Adapter.SelectCommand = cmd; //Adapter.SelectCommand.CommandTimeout = 1200;//可以设置适当的超时时间(秒),避免选择时间段过大导致填充数据集超时 Adapter.Fill(ds); } catch (Exception ex) { throw ex; } finally { this.Close(); } return ds; } /// <summary> /// 执行存储过程,方法不返回结果集 /// </summary> /// <param name="storedProcName"></param> public void RunVoidProcedure(string storedProcName) { cmd.CommandText = storedProcName; cmd.CommandType = CommandType.StoredProcedure; try { this.Open(); cmd.ExecuteNonQuery(); } catch (Exception ex) { throw ex; } finally { this.Close(); } } 下面说两个反射方法,测试之后为了方便调用,减少操作添加的,一个是把实体类的属性转换为参数,另一个是把从数据库取出的某条记录转换为实体类,这两个还是非常有用,尤其是在系统开发时调用比较方便,以前我是见到反射就绕道走的,这次算是第一次用反射,发现确实是很方便。如下: /// <summary> /// 将实体类的属性进行参数转换(ORACLE测试通不过,必须要求所有参数都包含在语句中才行) /// </summary> /// <param name="model"></param> /// <param name="ParaCollect"></param> //public void ConvertToParameters(object model, DbParameterCollection ParaCollect) //{ // Type T = model.GetType(); // PropertyInfo[] propert = T.GetProperties(); // for (int i = 0; i < propert.Length; i++) // { // AddParam(propert[i].Name, propert[i].GetValue(model, null), ParaCollect); // } //} /// <summary> /// 将实体类的属性进行参数转换 /// </summary> /// <param name="model"></param> /// <param name="ParaCollect"></param> public void ConvertToParameters(object model, DbParameterCollection ParaCollect,List<string> fields) { Type T = model.GetType(); PropertyInfo[] propert = T.GetProperties(); for (int i = 0; i < propert.Length; i++) { if (fields.Contains(propert[i].Name)) //检测必须参数化的实体属性 { AddParam(propert[i].Name, propert[i].GetValue(model, null), ParaCollect); } } } /// <summary> /// 通过反射将取出的数据写入实体类(ORACLE测试通不过,需进行类型强制转换) /// </summary> /// <param name="model"></param> /// <param name="cmdText"></param> //public void GetModel(object model, string cmdText) //{ // PropertyInfo propertyInfo; // DbDataReader dr = ExecuteDataReader(conn, cmdText); // while (dr.Read()) // { // for (int i = 0; i < dr.FieldCount; i++) // { // propertyInfo = model.GetType().GetProperty(dr.GetName(i)); // if (propertyInfo != null) // { // if (dr.GetValue(i) != DBNull.Value) // { // //Type t = dr.GetValue(i).GetType(); // propertyInfo.SetValue(model, dr.GetValue(i), null); // } // } // } // } // dr.Close(); // conn.Close(); //} /// <summary> /// 通过反射将数据绑定到实体对象,由于不同数据库对应于.NET的数据类型不一样 /// 需做强制类型转换 /// </summary> /// <param name="model"></param> /// <param name="cmdText"></param> public void GetModel(object model, string cmdText) { PropertyInfo propertyInfo; DbDataReader dr = ExecuteDataReader(conn, cmdText); object _value; while (dr.Read()) { for (int i = 0; i < dr.FieldCount; i++) { propertyInfo = model.GetType().GetProperty(dr.GetName(i)); if (propertyInfo != null && dr.GetValue(i) != DBNull.Value) { switch (propertyInfo.PropertyType.ToString()) { case "System.String": { _value = Convert.ToString(dr.GetValue(i));//字符串是全球通用类型,也可以不用转换 propertyInfo.SetValue(model, _value, null); }break; case "System.Int32": { _value = Convert.ToInt32(dr.GetValue(i)); propertyInfo.SetValue(model, _value, null); } break; case "System.Single": { _value = Convert.ToSingle(dr.GetValue(i)); propertyInfo.SetValue(model, _value, null); } break; case "System.Decimal": { _value = Convert.ToDecimal(dr.GetValue(i)); propertyInfo.SetValue(model, _value, null); } break; case "System.Double": { _value = Convert.ToDouble(dr.GetValue(i)); propertyInfo.SetValue(model, _value, null); } break; case "": { _value = Convert.ToDateTime(dr.GetValue(i)); propertyInfo.SetValue(model, _value, null); } break; default: break; } } } } dr.Close(); conn.Close(); } 从上面的注释掉的方法对比中可以看到为了兼容不同的数据库,必须要做额外的处理,比如类型转换,SQL SERVER的int 对应ORALCE的number,UserInfo的字段属性UserAge定义的是int类型,连接ORALCE时,.NET识别number类型为System.Decimal,把Decimal赋值给Int32当然是不行的,所以得做强制转换才行。还有一点要注意下,就是将数据绑定到实体对象时,由于ORACLE坚持大写标准和解析机制,如果属性名和字段名大小写不一致的话,propertyInfo = model.GetType().GetProperty(dr.GetName(i)) ,propertyInfo 始终是null值,比如SELECT UserName,UserAge FROM USER_TEST WHERE USERID=$USERID,SQL SERVER 执行的时候调试可以看到dr.GetName(0)是UserName,dr.GetName(1)是UserAge,ORACLE执行解析就变了,全是大写了,变成了USERNAE,USERAGE,这么一来和找不到UserInfo类的属性了,因为UserInfo类的属性是 UserName,和UserAge,C#语言变量也是区分大小写的嘛,当然就找不到了,所以propertyInfo就为null了,故在这里再次建议大家在数据库设计和程序字段属性设计时采用大写标准(如果不涉及多数据库当然也不需要这么做)。 (责任编辑:admin) |





骆驼户外男 真皮磨砂日常休闲鞋 低帮 2011秋冬新款 专柜正品特价