简体   繁体   English

打开/关闭 sql 连接的问题

[英]Problems with Open/Close sql connection

I hope you forgive my beginner's head.我希望你原谅我初学者的头。 I am having some problems with a code designed to open a connect to a SQL Server database.我在设计用于打开与 SQL Server 数据库的连接的代码时遇到了一些问题。

As you can see frmManageAppointment form is loaded from a different Winform.如您所见, frmManageAppointment表单是从不同的frmManageAppointment加载的。 So far so good.到现在为止还挺好。 Upon loading, the Connect() part of the code kicks in and connects to my SQL Server database.加载后,代码的Connect()部分启动并连接到我的 SQL Server 数据库。 So far so good.到现在为止还挺好。

I have a second script that load upon pressing the Save button on the form (basically saving a variety of textboxes and such).我有第二个脚本,在按下表单上的保存按钮时加载(基本上保存各种文本框等)。 My guess is that the second instance of conn in the MakeAppointment code somehow closed the connection, based on the error I am getting.我的猜测是MakeAppointment代码中的第二个 conn 实例以某种方式关闭了连接,基于我得到的错误。

I know I am not handling the script correctly so I would appreciate some help.我知道我没有正确处理脚本,所以我希望得到一些帮助。

namespace Scheduler1
{
    public partial class frmManageAppointment : Form
    {
        public frmManageAppointment()
        {
            InitializeComponent();
        }

        private void frmManageAppointment_Load(object sender, EventArgs e)
        {
            Connect();

            txtDBConnection.Text = "Connected";
        }

        private void ExitButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void SaveButton_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(txtSurname.Text))
            {
                MessageBox.Show("Απαιτείται το Επίθετο του Εξεταζόμενου!");
                return;
            }

            if (MakeAppointment())
            {
                MessageBox.Show("Επιτυχής Προσθήκη!");
            }
            else
            {
                MessageBox.Show("Ανεπιτυχής Προσθήκη");
            }
        }

        public void Connect()
        {
            string conString = "Data Source=DIMITRIS-PC\\DIMITRISSQL;Initial Catalog=AppointmentDB;Integrated Security=True";
            SqlConnection conn = new SqlConnection(conString);

            conn.Open();

            if (conn.State == System.Data.ConnectionState.Closed)
            {
                MessageBox.Show("Closed");
            }
            else if (conn.State == System.Data.ConnectionState.Open)
            {
                MessageBox.Show("Open");
            }
        }

        public Boolean MakeAppointment()
        {
            string conString = "Data Source=DIMITRIS-PC\\DIMITRISSQL;Initial Catalog=AppointmentDB;Integrated Security=True";
            SqlConnection conn = new SqlConnection(conString);
            string sql = "INSERT INTO Appointmentdbo(Date, Time, Name, Surname, DOB, PatientID, Comments) VALUES ('" + dtpDate.Value.Date.ToString("MM/dd/yyyy") + "','" + comboTime.Text + "','" + txtName.Text + "','" + txtSurname.Text + "','" + dtpDOB.Value.Date.ToString("MM/dd/yyyy") + "','" + txtID.Text + "','" + txtComments.Text + "')";

            SqlCommand cmd = new SqlCommand(sql, conn);

            return cmd.ExecuteNonQuery() > 0;
        }
    }
} 

As the comments pointed out, you're creating a connection (the conn object in Connect() , opening it, and then conn goes out of scope. It's the conn object here that IS the open connection.正如评论指出的那样,您正在创建一个连接( Connect()conn对象,打开它,然后conn超出范围。这里的conn对象是打开的连接。

Here's the shortest way to get this to work, but as the comments also state, this isn't really that great, either.这是使其工作的最短方法,但正如评论也指出的那样,这也不是那么好。 I laid this out to explain exactly what you were doing wrong/why what you had wasn't working.我提出这个是为了准确地解释你做错了什么/为什么你的东西不起作用。 Below this I have an example with using statements.下面我有一个using语句的例子。

public class frmManageAppointment : Form {

    SqlConnection conn; //private variable available to all methods in this class

    private void frmManageAppointment_Load(object sender, EventArgs e)
    {
        Connect();
    }

    private void ExitButton_Click(object sender, EventArgs e)
    {
        this.CloseConn(); //new method here
        this.Close();
    }

    void CloseConn() {
        //we want to close/dispose the connection obect
        conn.Close();
        conn.Dispose();
    }


    public void Connect()
    {
        string conString = "<constring>";
        conn = new SqlConnection(conString); //removed type here so conn now the class level variable
        conn.Open();
        //rest of code snipped        
    }

    public Boolean MakeAppointment()
    {
        string sql = "<sql string>"; //btw, the way you're generating this string is ... not ideal.  Google sql injection
        SqlCommand cmd = new SqlCommand(sql, conn); //conn is our global variable, which we're assuming here is still open/valid (not ideal)
        return cmd.ExecuteNonQuery() > 0;
    }

} }

The problem with this is that your form will be open for an indefinite length of time.这样做的问题是您的表单将无限期地打开。 This probably won't be an issue with a small app connecting to a local database where the app is the only thing connecting, but leaving the connection open wastes server resources and you have no guarantee that the conn object is still valid when you later try to use it in MakeAppointment() .这可能不是连接到本地数据库的小应用程序的问题,其中应用程序是唯一连接的东西,但保持连接打开会浪费服务器资源,并且您无法保证在稍后尝试时conn对象仍然有效在MakeAppointment()使用它。 You could add checks that it is actually open and call Connect() again if it's not, but that's a bunch of work for no gain.你可以添加检查它实际上是打开的,如果不是,则再次调用Connect() ,但这是一堆没有收获的工作。 A better pattern/habit to adopt when working with databases (or any network resource) is to only open them when you need to do work and close/release them as soon as you're done.使用数据库(或任何网络资源)时采用的更好模式/习惯是仅在需要工作时打开它们,并在完成后立即关闭/释放它们。 So that said, here's what your code would look like.也就是说,这就是您的代码的样子。

public class frmManageAppointment : Form {

    //no need for a Connect() method, conn global variable, or a CloseConn() method
    //your other methods pertaining to the UI would need to be copied over

    public Boolean MakeAppointment()
    {
        string sql = "<sql string>"; //again, what you're doing here is bad
        using(SqlConnection conn = new SqlConnection("<connectionstring>") {
            conn.Open();
            using(SqlCommand cmd = new SqlCommand(sql, conn)) {
                return cmd.ExecuteNonQuery() > 0;
            }
        }
    }
}

You only open the connection immediately before using it (the only place you're doing work in this example is in MakeAppointment() ), and by wrapping the connection and command in using statements, they're automatically disposed of (by calling those objects Dispose() method) as soon as they go out of scope.您只在使用它之前立即打开连接(在此示例中您唯一要做的工作是在MakeAppointment() ),并且通过将连接和命令包装在using语句中,它们会被自动处理(通过调用这些对象Dispose()方法)一旦超出范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM