为了防止Sql注入我们使用参数化查询的方法,为了节省Sql语句的编译时间我们使用存储过程,这两个看似毫不相干的东西,其实是同一个玩意,不信看我给你解释。
普通Sql语句可以增删改查,参数化查询和存储过程也可以增删改查,这里就不对四种操作逐个写例子了,写insert和select的例子来说明情况即可。

参数化查询:

执行参数化查询代码:

public static int ParamInsert(string userId, string userName, string gender)
{
    int rowNumber = -100;
    string connString = ConfigurationManager.ConnectionStrings["connString"].ToString();
    SqlConnection con = new SqlConnection(connString);
    con.Open();

    #region 参数化插入
    SqlCommand cmd1 = new SqlCommand("insert into UserInfo values(@userId,@userName,getdate(),@gender)", con);
    cmd1.Parameters.Add("@userId", SqlDbType.Int).Value = userId;
    cmd1.Parameters.Add("@userName", SqlDbType.NVarChar, 20).Value = userName;
    cmd1.Parameters.Add("@gender", SqlDbType.NVarChar, 2).Value = gender;
    rowNumber = cmd1.ExecuteNonQuery();
    cmd1.Dispose();
    #endregion

    #region 参数化查询
    SqlCommand cmd = new SqlCommand("select * from UserInfo where UserId = @UserId", con);
    cmd.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    DataSet ds = new DataSet();
    adapter.Fill(ds, "userInfo");
    DataTable dt = ds.Tables[0];
    DataRow row = dt.Rows[0];
    cmd.Dispose(); 
    #endregion

    con.Close();
    return rowNumber;
}

参数化查询与普通查询的区别在sql语句地书写上,
普通语句查询:
“select * from UserInfo where UserId = ” + userId
参数化查询:
“select * from UserInfo where UserId = @UserId”;
cmd.Parameters.Add();
普通语句插入:
string.Format(“insert into UserInfo values({0},{1},{2},{3})”,userId,userName,”getdate()”,gender);
参数化插入:
“insert into UserInfo values(@userId,@userName,getdate(),@gender)”;
cmd.Parameters.Add()
参数化查询是用@+字段名做标记表示此处要输入东西,然后通过cmd.Parameters.Add()对这些标记赋予具体类型并进行赋值。

存储过程:

创建insert存储过程代码

CREATE PROCEDURE [dbo].[Proc_InsertUserInfo]
    @UserId int,
    @UserName nvarchar(20),
    @AddTime datetime,
    @Gender nvarchar(2)
AS
BEGIN
    SET NOCOUNT ON;
    insert into dbo.UserInfo values(@UserId,@UserName,@AddTime,@Gender)

END

创建select存储过程代码

ALTER PROCEDURE [dbo].[Proc_SelectUserInfo]
    @UserId int
AS
BEGIN
    SET NOCOUNT ON;
    SELECT * from dbo.UserInfo where UserId=@UserId
END

执行存储过程代码:

public static int Insert(string userId,string userName,string gender)
{
    int rowNumber = -100;
    string strConnection = ConfigurationManager.ConnectionStrings["connString"].ToString();
    SqlConnection con = new SqlConnection(strConnection);
    con.Open();

    #region 存储过程插入
    SqlCommand cmd1 = new SqlCommand("Proc_InsertUserInfo", con);
    cmd1.CommandType = CommandType.StoredProcedure;
    cmd1.Parameters.Add("@UserId", SqlDbType.Int).Value = userId; ;
    cmd1.Parameters.Add("@UserName", SqlDbType.NVarChar, 20).Value = userName;
    cmd1.Parameters.Add("@AddTime", SqlDbType.DateTime).Value = DateTime.Now.ToString();
    cmd1.Parameters.Add("@Gender", SqlDbType.NVarChar, 2).Value = gender == "1" ? "男" : "女";
    rowNumber = cmd1.ExecuteNonQuery();
    cmd1.Dispose(); 
    #endregion

    #region 存储过程查询
    SqlCommand cmd = new SqlCommand("Proc_SelectUserInfo", con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    DataSet ds = new DataSet();
    rowNumber = adapter.Fill(ds, "userInfo");
    DataTable dt = ds.Tables[0];
    DataRow row = dt.Rows[0];
    #endregion

    con.Close(a);
    return rowNumber;
}

存储过程中的插入代码:
insert into dbo.UserInfo values(@UserId,@UserName,@AddTime,@Gender)
存储过程中的查询代码:
select * from dbo.UserInfo where UserId=@UserId
调用存储过程方式:
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add();
如果执行结果返回数据表,那也照样可以用SqlDataAdapter和DataSet来获取到,跟普通的Sql语句没什么两样,只不过存储过程需要先声明变量才能在Sql语句中使用,再者节省了Sql语句的编译时间,提高了效率。

结论

参数化查询和存储过程在声明方式和使用方式上大体相同,不同点有3:

  • 参数化查询直接用@+参数名作为参数化的标记,存储过程也是这样的,不过存储过程中要先声明一下这个标记的类型,才能使用
  • 参数化查询SqlCommand cmd = new SqlCommand(“Sql语句”, con);
    存储过程查询SqlCommand cmd = new SqlCommand(“存储过程名称”, con);
  • 调用存储过程要指明此处使用的是存储过程,cmd.CommandType =CommandType.StoredProcedure;,
    默认使用的是CommandType.Text