在C#中使用存储过程

我正在使用C#编写数据库应用程序。 我需要在表格上显示数据,现在我已经完成了。 但我的业务逻辑硬编码到我的代码。 现在我想继续使用我的代码存储过程。 我需要做哪些修改。 一个简单的步骤列表就够了:)

SqlConnection myConnection = new SqlConnection("user id=dbblabla;" + "password=1234;server=localhost\\SQLEXPRESS;" + "Trusted_Connection=yes;" + "database=myDB; " + "connection timeout=30"); try { myConnection.Open(); } catch (SqlException excep){ Console.WriteLine(excep.StackTrace); } String selectionQuery = "SELECT * FROM myTable"; SqlDataAdapter myAdapter = new SqlDataAdapter(selectionQuery,myConnection); DataSet ds = new DataSet(); myAdapter.Fill(ds,"AllInfo"); dataGridSearchOutput.DataSource = ds.Tables["AllInfo"].DefaultView; 

我从创建新的SQL命令开始,但我不确定我是否使用了正确的方法。

 SqlCommand newCommand = new SqlCommand("SELECT * FROM PMInfo"); newCommand.CommandType = CommandType.StoredProcedure; 

存储过程

 CREATE PROCEDURE addemp @eno int, @ename varchar(50), @edate datetime AS declare @p int select @p=count(*) from emp where eno=@eno if @p=0 begin insert into emp values (@eno,@ename,@edate) end RETURN 

C#代码

  SqlConnection cn = new SqlConnection(@"conn_str"); SqlCommand cmd = new SqlCommand("addemp", cn); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@eno", 10); cmd.Parameters.AddWithValue("@ename", "Mr.Xyz"); cmd.Parameters.AddWithValue("@edate", DateTime.Parse("1-1-2002")); cn.Open(); cmd.ExecuteNonQuery(); cn.Close(); 

存储过程

 CREATE PROCEDURE procedure AS BEGIN SET NOCOUNT ON; SELECT field1,field2 from tbl END GO 

 using(SqlConnection con = new SqlConnection("user id=dbblabla;password=1234;server=localhost\\SQLEXPRESS; database=myDB; connection timeout=30")) { SqlCommand cmd = new SqlCommand("procedure",con); cmd.CommandType= System.Data.CommandType.StoredProcedure; SqlDataAdapter da = new SqlDataAdapter(cmd); DataTable dt = new DataTable(); da.Fill(dt); dataGridSearchOutput.DataSource = dt; } 

我使用的原因是检查此链接

您只需要为SqlCommand构造函数指定存储过程名称,并将CommandType设置为CommandType.StoredProcedure 。 将一次性物品包裹在使用块中也是一种很好的做法。 SqlConnection,SqlCommand和SqlAdapter是一次性对象。 这是一个修改过的代码。

 string connectionString = "user id=dbblabla;" + "password=1234;server=localhost\\SQLEXPRESS;" + "Trusted_Connection=yes;" + "database=myDB; " + "connection timeout=30"; DataSet ds = new DataSet(); using(SqlConnection myConnection = new SqlConnection(connectionString)) using (SqlCommand command = new SqlCommand("yourprocedure", myConnection)) { SqlDataAdapter myAdapter = new SqlDataAdapter(); myAdapter.SelectCommand = command; myAdapter.Fill(ds,"AllInfo"); } dataGridSearchOutput.DataSource = ds.Tables["AllInfo"].DefaultView; 

我不明白为什么人们在数据访问代码方面忘记了他们是面向对象的语言。 你不应该一遍又一遍地编写相同的代码。 首先,您应该有一个在所有项目中使用的基类。 这个基类应该处理连接字符串,记录exception等等。我在一年前写过并且之后没有改变它。

请查看以下有关此基类中的示例:

 protected SqlCommand GetNewCmd() { SqlCommand objCmd = new SqlCommand(); objCmd.Connection = new SqlConnection(this.ConnString); objCmd.CommandType = CommandType.StoredProcedure; return objCmd; } protected SqlCommand GetNewCmd(string CmdText) { SqlCommand objCmd = new SqlCommand(CmdText, new SqlConnection(this.ConnString)); objCmd.CommandType = CommandType.StoredProcedure; return objCmd; } protected DataTable GetTable(SqlCommand objCmd) { DataTable dt = new DataTable(); SqlDataAdapter da = new SqlDataAdapter(); try { da.SelectCommand = objCmd; da.Fill(dt); dt.DefaultView.AllowNew = false; } catch (Exception ex) { LogException(ex); throw; } finally { Close(objCmd); da.Dispose(); da = null; } return dt; } 

我们有GetTable(),GetDataSet(),ExecuteScalarInt(),ExecuteScalarGuid()等,每个都有一堆重载。

所以这些都在我的基类中,我从这个类inheritance来完成我的项目特定工作。 但是现在这个例子大大简化了:

 public DataTable GetStages(int id) { SqlCommand cmd = GetNewCmd("dbo.GetStages"); cmd.Parameters.Add("@ID", SqlDbType.Int).Value = id; return GetTable(cmd); } public void DeleteStage(int id) { SqlCommand cmd = GetNewCmd("dbo.DeleteStage"); cmd.Parameters.Add("@ID", SqlDbType.Int).Value = id; ExecuteNonQuery(cmd); } 

作为附带好处,我可以根据存储过程脚本编写此代码。 这是执行此操作的代码。 所以它节省了很多打字,特别是当有很多参数时。

最后,使用其他面向对象的技术,我将代码简化为以下内容:

 GridView1.DataSource = cApp.DB.GetStages(id); GridView1.DataBind(); 

(大多数情况下,中间有一个业务对象,但你明白了。)所有的连接字符串,exception日志记录等都封装在那一行中。

另一个好处是,如果每次复制代码,您的基类可能会更加复杂。 例如,我们将exception记录到数据库表中。 只有在失败的情况下才会将其记录到文本文件中。 如果它存在于基类中的一个位置,那么这种广泛的逻辑很好,但它不是你想要复制并粘贴到项目中的东西。

这也可以很容易地结合一些最佳实践,例如尽可能晚地打开连接并尽快关闭它。

 SqlCommand newCommand = new SqlCommand("SELECT * FROM PMInfo"); newCommand.CommandType = CommandType.StoredProcedure; 

这将无法正常工作,因为您没有使用存储过程,应该像这样调用上面的命令

 SqlCommand newCommand = new SqlCommand("SELECT * FROM PMInfo"); newCommand.CommandType = CommandType.Text; 

如果您正在调用存储过程,您可以这样调用它:

 SqlCommand newCommand = new SqlCommand("spYourProcedure"); newCommand.CommandType = CommandType.StoredProcedure; 

有关详细信息,请参阅MSDN中的此处 ,它还将使用参数

使用查询只有一些区别:

  SqlDataAdapter myAdapter = new SqlDataAdapter(); myAdater.Connection = myConnection; SqlCommand newCommand = new SqlCommand("spPminfoList"); newCommand.CommandType = CommandType.StoredProcedure; myAdapter.SelectCommand = newCommand; 

当然,您必须在数据库中创建spPminfoList。

存储过程示例:

  CREATE PROCEDURE dbo.AddEmp @code varchar(10), @name varchar(10), @address varchar(10) AS INSERT INTO Employee (Code,NameEmp,Address) VALUES (@code,@name,@address) RETURN 

C#代码:

  private void AddButton_Click(object sender, EventArgs e) { con.Open(); SqlCommand cmd = new SqlCommand("AddEmp", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@code", SqlDbType.VarChar).Value = textBox1.Text.Trim(); cmd.Parameters.AddWithValue("@name", SqlDbType.VarChar).Value = textBox2.Text.Trim(); cmd.Parameters.AddWithValue("@address", SqlDbType.VarChar).Value = textBox3.Text.Trim(); cmd.ExecuteNonQuery(); MessageBox.Show("Employee added"); con.Close(); } 

有关更多说明,请参阅本教程使用存储过程和C#初学者

这不完全是你的问题的答案,但在你的情况下,我不会打扰你的查询到存储过程,因为它可能是很多额外的工作,没有真正的好处。 在过去的日子里,SQL Server中的存储过程比所谓的即席SQL查询更快,因为SQL Server可以计算和缓存查询的执行计划。 但是,在SQL Server的现代版本中,数据库将在每次查询运行一次后缓存执行计划,因此在初始执行即席查询后,它将像存储过程一样快地执行。

此外,在您的应用程序代码中保留查询的一个真正的主要优点是查询将受源代码控制和版本控制(假设您当前正在使用源代码控制)。 可以在SQL Server中对存储过程进行版本化,但这是更多的工作,人们很少这样做。

最后,将查询移动到存储过程将意味着重写应用程序代码的大部分内容,因为存储过程的访问方式与ad hoc SQL查询的访问方式不同。 在开始时使用存储过程编写应用程序可能是有意义的,但在将应用程序编写为使用临时SQL查询之后,将应用程序转换为使用存储过程的意义却大不了。

对于它的价值而言,除了简单地将存储过程包装在代码隐藏中之外,您还需要做很多事情。 有关远景的一些见解,请查看这篇文章:

道路上的代码:ExampleCode!= ProductionCode

Ad-hoc SQL是最简单的修复方法之一,但是我们作为开发人员遇到的最常见的代码重复forms。 即使只是几分钟的思考如何组织数据库交互,也会以可维护性和开发速度的forms获得成功。

public class CustomerDataAccess {static string connectionstring = ConfigurationManager.ConnectionStrings [“testDB”]。ToString(); public List GetCustomerListByName(string customerName){List customerList = new List();