C# 在C中使用存储过程#

C# 在C中使用存储过程#,c#,.net,database,stored-procedures,C#,.net,Database,Stored Procedures,我正在用C#开发一个数据库应用程序。我需要在表上显示数据,现在我已经完成了。但我的业务逻辑是硬编码到我的代码中的。现在,我想继续,在代码中使用存储过程。我需要做哪些修改。一个简单的步骤列表就足够了:) 我从创建一个新的SQL命令开始,但我不确定我使用的方法是否正确 SqlCommand newCommand = new SqlCommand("SELECT * FROM PMInfo"); newCommand.CommandType = CommandType.StoredProcedure;

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

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

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

使用查询只有几个不同之处:

   SqlDataAdapter myAdapter = new SqlDataAdapter(); 
   myAdater.Connection = myConnection;

   SqlCommand newCommand = new SqlCommand("spPminfoList");
   newCommand.CommandType = CommandType.StoredProcedure;
   myAdapter.SelectCommand = newCommand;
当然,您必须在数据库中创建spPminfoList

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中的,它还将介绍如何使用参数存储过程

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#代码


这并不能完全回答您的问题,但对于您的情况,我不想麻烦您将查询转换为存储过程,因为这可能会带来大量额外的工作,而没有实际的好处。在过去,SQL Server中的存储过程比所谓的即席SQL查询更快,因为SQL Server可以计算和缓存查询的执行计划。但是,在SQL Server的现代版本中,数据库将在每个查询运行一次后缓存其执行计划,因此在临时查询的初始执行之后,它的执行速度将与存储过程一样快

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


最后,将查询移动到存储过程将意味着重写应用程序代码的大部分,因为存储过程的访问方式与特殊SQL查询不同。在一开始使用存储过程编写应用程序可能是有意义的,但是,在编写应用程序以使用特殊SQL查询之后,将其转换为使用存储过程的意义要小得多。

只需将存储过程名称指定给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;
存储过程

CREATE PROCEDURE  procedure 

AS
BEGIN

    SET NOCOUNT ON;
    SELECT field1,field2 from tbl
END
GO
代码


我使用的原因是检查一下这个

它的价值,您需要做的不仅仅是简单地将存储过程包装在codebehind中。要深入了解距离,请查看本文:


Ad-hoc-SQL是最容易修复的代码复制形式之一,也是我们作为开发人员遇到的最常见的代码复制形式之一。即使只花几分钟思考如何组织数据库交互,也会在可维护性和开发速度方面获得巨大的回报。

我不明白为什么人们在数据访问代码方面忘记了他们使用的是面向对象的语言。您不应该一遍又一遍地编写相同的代码。首先,您应该有一个在所有项目中使用的基类。这个基类应该负责连接字符串、日志异常等。我一年前写的,从那以后就没有做太多更改

请参阅以下内容,以获取此基类中的示例:

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()、executescalarrint()、ExecuteScalarGuid()等,每个都有一系列重载

这些都在我的基类中,我从这个类继承来做我特定于项目的工作。但现在这被大大简化了,如以下示例所示:

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();

(大多数时候中间有一个业务对象,但你知道了。) 所有连接字符串、异常日志记录等都封装在这一行中

另一个好处是,与每次复制代码相比,您的基类可以得到更多的参与。例如,我们将异常记录到数据库表中。只有在失败的情况下,才会将其记录到文本文件中。如果它位于基类中的一个位置,那么这种广泛的逻辑是很好的,但是您不想在整个项目中复制和粘贴它


这也使得合并一些最佳做法变得容易,例如尽可能晚地打开连接并尽快关闭连接。

存储过程示例:

    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#代码:


有关更多说明,请查看本教程

公共类CustomerDataAccess { 静态字符串connectionstring=ConfigurationManager.connectionstring[“testDB”].ToString(); 公共列表GetCustomerListByName(字符串customerName) {
List customerList=new List();

sqlDataAdapter构造函数不接受连接作为参数:(这里还有另一个问题..我已经在我的DBMS中定义了SP..即在MSSQL2005中。那么程序如何知道“spPminfoList”存储过程是否与myConnection关联?我更正了适配器ctor,切换到StoredProc的命令在CommandType属性中(如您的问题所示)。顺便说一句,其中有几个类是IDisposable的。您需要在生产代码中处理它们以关闭连接、释放资源等。请查找IDisposable、using语句和(如果需要)基本的处置模式。这将帮助你避免资源泄漏。这个假威尔家伙到底是谁?我显然是真正的威尔,因为我是第一个!伪装者!真的会吗
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();
    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
    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();
    }