部分摘自asp.net3.5从入门到精通c#2008
asp.net要执行删除和更新操作实际并不复杂,只要使用一个数据命令(Command)对象,使用Update, Insert 或者Delete 这三个语句之一。在执行删除、更新或插入操作时,并不需要获取获取数据,因此也并不需要使用DataReader对象。
要执行Updata、Insert或者 Delete语句,只需要创建一个数据命令(Command)对象,然后调用其ExecuteNonQuery()方法来执行数据命令。ExecuteNonQuery()方法将返回受影响的记录数,可以通过检查该方法的返回值,以判断对数据库的操作是否执行成功。例如,如果试图执行一个更新或者删除操作,但是ExecuteNonQuery()方法的返回值为0,则表示操作失败,这个能使由于数据库中并不存在于Where子句中的筛选条件相匹配的记录。(另外,如果该SQL命令具有语法错误,或者该SQL命令试图检索一个数据库中并不存在的表时,将会产生异常。)
这里只说一下更新的方法,先是不安全的代码:
string insertSQL;
insertSQL = " INSERT INTO Authors ( " ;
insertSQL += " au_id, au_fname, au_lname, " ;
insertSQL += " phone, adress, sity, state, zip, contract) " ;
insertSQL += " VALUES (' " ;
insertSQL += txtID.Text + " ', ' " ;
insertSQL += txtFirstName.Text + " ', ' " ;
insertSQL += ...
...
...
insertSQL += txtZip.Text + " ') " ;
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(insertSQL, con);
// 尝试打开数据库连接并执行更新。
int added = 0 ;
try
{
con.Open();
added = cmd.ExecteNonQuery();
lblStatus.Text = added.ToString() + " records inserted. " ;
}
catch (Exception err)
{
lblStatus.Text = " Error inserting record. " ;
lblStatus.Text += err.Message;
}
finally
{
con.Close();
}
// added判断操作是否成功
这个例子是把字符串在代码中连接起来组成一个SQL字符串,然后再通过command执行这个动态生成的SQL语句。这个办法虽然简单但是存在很大的缺陷,如果用户无意或有意的输入一些特殊字符如单引号(')或者注入一些恶意代码,后果就严重了。
为了创建更加稳定的数据命令,可以使用ado.net的参数化数据命令(parameterized command)。在参数化数据命令中,使用参数作为占位符来替代硬编码的值。下面是更改后的代码(更改的地方用下划线):
string insertSQL;
insertSQL = " INSERT INTO Authors ( " ;
insertSQL += " au_id, au_fname, au_lname, " ;
insertSQL += " phone, adress, sity, state, zip, contract) " ; "
insertSQL += " VALUES (' " ;
insertSQL += "@au_id, @au_fname, @au_lname, ";
insertSQL += "@phone, @address, @city, @state, @zip, @contract)" ;
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(insertSQL, con);
cmd.Parameters.AddWithValue( "@au_id", txtID.Text);
cmd.Parameters.AddWithValue("@au_fname", txtFirstName.Text);
cmd.Parameters.AddWithValue("@au_lname", txtLastName.Text);
cmd.Parameters.AddWithValue("@phone", txtPhone.Text);
...
...
...
cmd.Parameters.AddWithValue("@zip" , txtZip.Text);
// 尝试打开数据库连接并执行更新。
int added = 0 ;
try
{
con.Open();
added = cmd.ExecteNonQuery();
lblStatus.Text = added.ToString() + " records inserted. " ;
}
catch (Exception err)
{
lblStatus.Text = " Error inserting record. " ;
lblStatus.Text += err.Message;
}
finally
{
con.Close();
}
// added判断操作是否成功
对于不同的数据提供程序,参数化数据命令的语法是不同的。对于SQL Server,参数名可以任意选取,但是必须以@字符开通。通常情况下我们将@使用的字段名作为相应的参数名。而OLE DB是用?来占位。通过addwithvalue来添加parameter对象,当然添加的顺序是无关紧要的。
这样在参数中出现的引号或者SQL语句片段将不会对SQL命令的执行造成任何问题。
书上的描述到这里为止,看了一下网上的其实还有另一种添加方法:Parameters.Add(...),它和之前的Parameters.AddWithValue(...)区别是:
" 在.Net Framework 2.0中SqlClient增加了AddWithValue(string parameterName, object value)方法。
该方法简化了调用储存过程的输入参数过程,在运行时对所输入的数据类型进行判断,获取对应的数据库类型。
因此该方法在运行效率上比用Add(string parameterName, SqlDbType sqlDbType, int size, string sourceColumn)方法要低。
在效率要求较高的地方仍然建议使用Add()方法,其它场合可以使用AddWithValue()简化代码编写量。"
效率的话有说这个高的也又说那个高的,不太清楚
据网上说Parameters.AddWithValue在传入数据是DataTime的时候会出错。
我觉得为了保险还是用Add比较好。
下面贴一段我自己用Add的代码,这里先放到一个sqlparameter对象里再一起加入。
try
{conn = new SqlConnection(ConfigurationManager.ConnectionStrings[ " nd_dataConnectionString " ].ConnectionString); // 取连接字符串,建立连接
conn.Open();
comm = new SqlCommand( " update nd_cn set name=@name,text=@text where id= " + textid, conn);
SqlParameter[] pars = { new SqlParameter( " @name " ,SqlDbType.NVarChar, 50 ),
new SqlParameter( " @text " ,SqlDbType.Text)};
pars[ 0 ].Value = TextBox1.Text;
pars[ 1 ].Value = tbContent.Text;
foreach (SqlParameter parameter in pars)
{
comm.Parameters.Add(parameter);
}
comm.ExecuteNonQuery();
}
catch (SqlException e1)
{
Response.Write(e1.ToString());
}
finally
{
conn.Close();
}
里面的SqlDbType要区分大小写,具体有哪些的话请参看msdn中表格:
说明 | ||
---|---|---|
BigInt | Int64. 64 位带符号整数。 | |
Binary | Byte 类型的 Array。 二进制数据的固定长度流,范围在 1 到 8,000 个字节之间。 | |
Bit | Boolean. 无符号数值,可以是 0、1 或 null。 | |
Char | String. 非 Unicode 字符的固定长度流,范围�� 1 到 8,000 个字符之间。 | |
DateTime | DateTime. 日期和时间数据,值范围从 1753 年 1 月 1 日到 9999 年 12 月 31 日,精度为 3.33 毫秒。 | |
Decimal | Decimal. 固定精度和小数位数数值,在 -10 38 -1 和 10 38 -1 之间。 | |
Float | Double. -1.79E +308 到 1.79E +308 范围内的浮点数。 | |
Image | Byte 类型的 Array。 二进制数据的可变长度流,范围在 0 到 2 31 -1(即 2,147,483,647)字节之间。 | |
Int | Int32. 32 位带符号整数。 | |
Money | Decimal. 货币值,范围在 -2 63(即 -922,337,203,685,477.5808)到 2 63 -1(即 +922,337,203,685,477.5807)之间,精度为千分之十个货币单位。 | |
NChar | String. Unicode 字符的固定长度流,范围在 1 到 4,000 个字符之间。 | |
NText | String. Unicode 数据的可变长度流,最大长度为 2 30 - 1(即 1,073,741,823)个字符。 | |
NVarChar | String. Unicode 字符的可变长度流,范围在 1 到 4,000 个字符之间。 如果字符串大于 4,000 个字符,隐式转换会失败。 在使用比 4,000 个字符更长的字符串时,请显式设置对象。 | |
Real | Single. -3.40E +38 到 3.40E +38 范围内的浮点数。 | |
UniqueIdentifier | Guid. 全局唯一标识符(或 GUID)。 | |
SmallDateTime | DateTime. 日期和时间数据,值范围从 1900 年 1 月 1 日到 2079 年 6 月 6 日,精度为 1 分钟。 | |
SmallInt | Int16. 16 位的带符号整数。 | |
SmallMoney | Decimal. 货币值,范围在 -214,748.3648 到 +214,748.3647 之间,精度为千分之十个货币单位。 | |
Text | String. 非 Unicode 数据的可变长度流,最大长度为 2 31 -1(即 2,147,483,647)个字符。 | |
Timestamp | Byte 类型的 Array。 自动生成的二进制数字,它们保证在数据库中是唯一的。 timestamp 通常用作为表行添加版本戳的机制。 存储大小为 8 字节。 | |
TinyInt | Byte. 8 位无符号整数。 | |
VarBinary | Byte 类型的 Array。 二进制数据的可变长度流,范围在 1 到 8,000 个字节之间。 如果字节数组大于 8,000 个字节,隐式转换会失败。 在使用比 8,000 个字节大的字节数组时,请显式设置对象。 | |
VarChar | String. 非 Unicode 字符的可变长度流,范围在 1 到 8,000 个字符之间。 | |
Variant | Object. 特殊数据类型,可以包含数值、字符串、二进制或日期数据,以及 SQL Server 值 Empty 和 Null,后两个值在未声明其他类型的情况下采用。 | |
Xml | XML 值。 使用 GetValue 方法或 Value 属性获取字符串形式的 XML,或通过调用 CreateReader 方法获取 XmlReader 形式的 XML。 | |
Udt | SQL Server 2005 用户定义的类型 (UDT)。 | |
Structured | 指定表值参数中包含的构造数据的特殊数据类型。 | |
Date | 日期数据,值范围从公元 1 年 1 月 1 日到公元 9999 年 12 月 31 日。 | |
Time | 基于 24 小时制的时间数据。 时间值范围从 00:00:00 到 23:59:59.9999999,精度为 100 毫微秒。 对应于 SQL Server time 值。 | |
DateTime2 | 日期和时间数据。 日期值范围从公元 1 年 1 月 1 日到公元 9999 年 12 月 31 日。 时间值范围从 00:00:00 到 23:59:59.9999999,精度为 100 毫微秒。 | |
DateTimeOffset | 显示时区的日期和时间数据。 日期值范围从公元 1 年 1 月 1 日到公元 9999 年 12 月 31 日。 时间值范围从 00:00:00 到 23:59:59.9999999,精度为 100 毫微秒。 时区值范围从 -14:00 到 +14:00。 |
最后再贴一段类似的代码提供比较
try
{
openCon();
// sTran = con.BeginTransaction(); // 事务对象
cmd = new SqlCommand(sql,con);
// cmd.Transaction = sTran; // 执行事务
// try
// {
// 调用存储过程
cmd.CommandType = CommandType.StoredProcedure;
// 添加参数
SqlParameter[] pars = { new SqlParameter( " @FartherTypeID " ,SqlDbType.Int),
new SqlParameter( " @DetailTypeID " ,SqlDbType.Int),
new SqlParameter( " @LevelTypeID " ,SqlDbType.Int),
new SqlParameter( " @BookName " ,SqlDbType.VarChar, 50 ),
new SqlParameter( " @MarketPrice " ,SqlDbType.Money),
new SqlParameter( " @MenberPrice " ,SqlDbType.Money),
new SqlParameter( " @Rebate " ,SqlDbType.Float),
new SqlParameter( " @BookWriter " ,SqlDbType.VarChar, 100 ),
new SqlParameter( " @BookConcern " ,SqlDbType.VarChar, 50 ),
new SqlParameter( " @ISBN " ,SqlDbType.VarChar, 20 ),
new SqlParameter( " @BookIntroduce " ,SqlDbType.VarChar, 5000 ),
new SqlParameter( " @AddDateTime " ,SqlDbType.DateTime),
new SqlParameter( " @BookPicture " ,SqlDbType.VarChar, 200 ),
};
foreach (SqlParameter parameter in pars)
{
cmd.Parameters.Add(parameter);
}
return cmd.ExecuteNonQuery();
}
看看麻烦一点 其实用起来还好的