C# TSQL 存储过程不传递参数?
C# TSQL Stored Procedure don't pass parameter?
我不知道这个查询是否值得询问,但最好了解什么有效和无效以及为什么。
我有一个像这样的 table 叫做 tbl_Person_Details
:
ID | Name | Likes
-----------------
0 | Jon | Fish
1 | Doey | Coding
像这样隐藏代码(示例显示了两个函数,但可能还有更多):
public void updatePerson()
{
string sID = GridView1.SelectedDataKey[0].ToString();
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
con.Open();
SqlCommand comm = new SqlCommand("spUpdatePersonBasics", con);
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("@Name", tbName.Text.ToString()));
comm.Parameters.Add(new SqlParameter("@ID", sID));
object tmp = comm.ExecuteScalar();
con.Close();
lblStatus.Text = "<img src=\"img/icons/green-tick.gif\" /> <strong>>Person Details have been updated!</strong>";
}
public void updatePersonLikes()
{
string sID = GridView1.SelectedDataKey[0].ToString();
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
con.Open();
SqlCommand comm = new SqlCommand("spUpdatePersonBasics", con);
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("@Likes", tbName.Text.ToString()));
comm.Parameters.Add(new SqlParameter("@ID", sID));
object tmp = comm.ExecuteScalar();
con.Close();
lblStatus.Text = "<img src=\"img/icons/green-tick.gif\" /> <strong>>Person likes have been updated!</strong>";
}
存储过程:
ALTER PROCEDURE [dbo].[spUpdatePersonBasics]
@ID int,
@Name varchar(50),
@Likes varchar(50)
AS
UPDATE tbl_Person_Details
SET Name = @Name,
Likes = @Likes
WHERE ID = @ID
SELECT CAST(scope_identity() AS int)
问题:
正如我们所看到的,到目前为止一切都很好。但是,在调试时,我们可能会遇到多个导致问题的场景。这些如下:
- 在我的代码隐藏函数中,即使有时我只想更新一个参数,我也必须声明所有参数。
- 如果我们添加一个名为 'Title' 的新列,并且前端 HTML 有一个下拉列表。我们可以通过向存储过程添加一行并向任何函数添加一行参数来更新后面的代码。但是因为现在存储过程将有一个新参数,然后在我们没有更新 'Title' 的代码隐藏函数中,我们将得到一个 SQL 异常错误,因为我们没有通过这个给定的函数返回数据存储过程。
我认为这里的设计很糟糕,但我认为对我来说唯一可能的解决方案是拥有多个存储过程,即每个函数一个。如果这是最好的方法并且是否可靠,有什么想法吗?
我真正需要的是不更新某些已经存在的列。例如,我不想在更新点赞时更新行的名称。
你 可以 只需传入 NULL
两个值之一,如果你不想更新它,然后调整你的存储过程以这个:
ALTER PROCEDURE [dbo].[spUpdatePersonBasics]
@ID int,
@Name varchar(50),
@Likes varchar(50)
AS
UPDATE tbl_Person_Details
SET Name = ISNULL(@Name, Name)
Likes = ISNULL(@Likes, Likes)
WHERE ID = @ID
因此,如果您传入 @Name = NULL
,那么 UPDATE
基本上会将 Name
更新为 Name
的值 - "non-update",真的。
要从 C# 传递 NULL,请使用 DBNull.Value
:
comm.Parameters.Add("@Name", SqlDbType.VarChar, 50).Value = DBNull.Value;
我选择使用.Add()
方式,我选择显式指定参数SqlDbType
(包括长度,对于string-based参数)
如果你想传递参数 - 只需使用这个:
comm.Parameters.Add("@Name", SqlDbType.VarChar, 50).Value = tbName.Text;
因为 .Text
属性 已经 是一个 string
,所以调用 .ToString()
真的没有意义。 ...
我不知道这个查询是否值得询问,但最好了解什么有效和无效以及为什么。
我有一个像这样的 table 叫做 tbl_Person_Details
:
ID | Name | Likes
-----------------
0 | Jon | Fish
1 | Doey | Coding
像这样隐藏代码(示例显示了两个函数,但可能还有更多):
public void updatePerson()
{
string sID = GridView1.SelectedDataKey[0].ToString();
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
con.Open();
SqlCommand comm = new SqlCommand("spUpdatePersonBasics", con);
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("@Name", tbName.Text.ToString()));
comm.Parameters.Add(new SqlParameter("@ID", sID));
object tmp = comm.ExecuteScalar();
con.Close();
lblStatus.Text = "<img src=\"img/icons/green-tick.gif\" /> <strong>>Person Details have been updated!</strong>";
}
public void updatePersonLikes()
{
string sID = GridView1.SelectedDataKey[0].ToString();
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
con.Open();
SqlCommand comm = new SqlCommand("spUpdatePersonBasics", con);
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("@Likes", tbName.Text.ToString()));
comm.Parameters.Add(new SqlParameter("@ID", sID));
object tmp = comm.ExecuteScalar();
con.Close();
lblStatus.Text = "<img src=\"img/icons/green-tick.gif\" /> <strong>>Person likes have been updated!</strong>";
}
存储过程:
ALTER PROCEDURE [dbo].[spUpdatePersonBasics]
@ID int,
@Name varchar(50),
@Likes varchar(50)
AS
UPDATE tbl_Person_Details
SET Name = @Name,
Likes = @Likes
WHERE ID = @ID
SELECT CAST(scope_identity() AS int)
问题:
正如我们所看到的,到目前为止一切都很好。但是,在调试时,我们可能会遇到多个导致问题的场景。这些如下:
- 在我的代码隐藏函数中,即使有时我只想更新一个参数,我也必须声明所有参数。
- 如果我们添加一个名为 'Title' 的新列,并且前端 HTML 有一个下拉列表。我们可以通过向存储过程添加一行并向任何函数添加一行参数来更新后面的代码。但是因为现在存储过程将有一个新参数,然后在我们没有更新 'Title' 的代码隐藏函数中,我们将得到一个 SQL 异常错误,因为我们没有通过这个给定的函数返回数据存储过程。
我认为这里的设计很糟糕,但我认为对我来说唯一可能的解决方案是拥有多个存储过程,即每个函数一个。如果这是最好的方法并且是否可靠,有什么想法吗?
我真正需要的是不更新某些已经存在的列。例如,我不想在更新点赞时更新行的名称。
你 可以 只需传入 NULL
两个值之一,如果你不想更新它,然后调整你的存储过程以这个:
ALTER PROCEDURE [dbo].[spUpdatePersonBasics]
@ID int,
@Name varchar(50),
@Likes varchar(50)
AS
UPDATE tbl_Person_Details
SET Name = ISNULL(@Name, Name)
Likes = ISNULL(@Likes, Likes)
WHERE ID = @ID
因此,如果您传入 @Name = NULL
,那么 UPDATE
基本上会将 Name
更新为 Name
的值 - "non-update",真的。
要从 C# 传递 NULL,请使用 DBNull.Value
:
comm.Parameters.Add("@Name", SqlDbType.VarChar, 50).Value = DBNull.Value;
我选择使用.Add()
方式,我选择显式指定参数SqlDbType
(包括长度,对于string-based参数)
如果你想传递参数 - 只需使用这个:
comm.Parameters.Add("@Name", SqlDbType.VarChar, 50).Value = tbName.Text;
因为 .Text
属性 已经 是一个 string
,所以调用 .ToString()
真的没有意义。 ...