【问题标题】:SQL changes disappear after VS restartVS重启后SQL更改消失
【发布时间】:2015-05-05 12:20:30
【问题描述】:

我正在学习 C# 和 SQL 交互的基础知识,我有这种形式:

它向我显示了使用 VS 2013 数据库构建器制作的预填充数据库中的值,并且上部按钮一切正常

这是我的桌子:

问题:

  • 当我单击添加新时,文本框被清除;
  • 接下来,填充文本框,当我单击“保存”时,该记录显然已添加到 DB(或至少添加到 DataSet?),因为它给了我一条成功的消息,并在我使用上部导航浏览 DB 时显示按钮;
  • 如果我关闭并重新打开我的应用程序(不关闭 VS),我插入的记录仍然存在
  • 但是如果我关闭并重新打开 VS 并再次运行我的应用程序,我输入的记录消失了
  • 另外,在不关闭 VS 的情况下,如果我转到服务器资源管理器(VS 左窗格),右键单击我的表 => 显示表数据,新记录永远不会出现。

这是 Form1.cs 代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SQLtest
{
/// <summary>
/// A class that constains our form
/// </summary>
public partial class Form1 : Form
{
    // variables
    DBconnection objConnect;
    string conString;
    DataSet ds;
    DataRow dr;
    int maxRows;
    int inc = 0;

    /// <summary>
    /// Constructor of the class
    /// </summary>
    public Form1()
    {
        InitializeComponent();
    }

    /// <summary>
    /// Form initialization method
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Form1_Load(object sender, EventArgs e)
    {
        try
        {
            objConnect = new DBconnection();
            conString = Properties.Settings.Default.TestConnectionString;

            objConnect.connection_string = conString;
            objConnect.Sql = Properties.Settings.Default.SQL;

            ds = objConnect.GetConnection;

            maxRows = ds.Tables[0].Rows.Count;
            // MessageBox.Show("Max Rows: " + maxRows);

            NavigateRecords();
        }
        catch (Exception err)
        {
            MessageBox.Show(err.Message);
        }
    }

    // DB Navigation Methods

    /// <summary>
    /// Sets pointer (inc) to last row
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnNext_Click(object sender, EventArgs e)
    {
        // prevent indexOutOfBounds error
        if (inc != maxRows - 1)
        {
            inc++;
            NavigateRecords();
        }
        else
        {
            MessageBox.Show("Reached last employee. Showing the first record.");
            inc = 0;
            NavigateRecords();
        }

    }

    /// <summary>
    /// Sets pointer (inc) to previous row (if possible)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnPrevious_Click(object sender, EventArgs e)
    {
        // prevent indexOutOfBounds error
        if (inc != 0)
        {
            inc--;
            NavigateRecords();
        }
        else
        {
            MessageBox.Show("Reached first employee. Showing the last record.");
            inc = maxRows - 1;
            NavigateRecords();
        }
    }

    /// <summary>
    /// Sets pointer (inc) to first row
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnFirst_Click(object sender, EventArgs e)
    {
        if (inc != 0)
        {
            inc = 0;
            NavigateRecords();
        }
        else
        {
            MessageBox.Show("Already on first employee.");
        }
    }

    /// <summary>
    /// Sets pointer (inc) to last row
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnLast_Click(object sender, EventArgs e)
    {
        if (inc != maxRows - 1)
        {
            inc = maxRows - 1;
            NavigateRecords();
        }
        else
        {
            MessageBox.Show("Already on last employee.");
        }
    }

    /// <summary>
    /// Main Navigation Method
    /// </summary>
    private void NavigateRecords()
    {
        dr = ds.Tables[0].Rows[inc];

        txtFirstName.Text = dr.ItemArray.GetValue(1).ToString();
        txtLastName.Text = dr.ItemArray.GetValue(2).ToString();
        txtJobTitle.Text = dr.ItemArray.GetValue(3).ToString();
        txtDepartment.Text = dr.ItemArray.GetValue(4).ToString();
    }

    /// <summary>
    /// Exit button handler
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnExit_Click(object sender, EventArgs e)
    {
        Application.Exit();
    }

    /// <summary>
    /// Add new record Button. Simply clears text fields, ready for a new record to be added.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnAddNew_Click(object sender, EventArgs e)
    {
        txtFirstName.Clear();
        txtLastName.Clear();
        txtJobTitle.Clear();
        txtDepartment.Clear();

        btnAddNew.Enabled = false;
        btnSave.Enabled = true;
        btnCancel.Enabled = true;
    }

    /// <summary>
    /// Save a new record button
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnSave_Click(object sender, EventArgs e)
    {
        DataRow newRow = ds.Tables[0].NewRow();

        // newRow[0] is the id, thus its filled automatically
        newRow[1] = txtFirstName.Text;
        newRow[2] = txtLastName.Text;
        newRow[3] = txtJobTitle.Text;
        newRow[4] = txtDepartment.Text;

        ds.Tables[0].Rows.Add(newRow);

        try
        {
            objConnect.UpdateDB(ds);
            maxRows++;
            inc = maxRows - 1;

            MessageBox.Show("DB updated successfully");
        }
        catch (Exception err)
        {
            MessageBox.Show(err.Message);
        }

        btnAddNew.Enabled = true;
        btnSave.Enabled = false;
        btnCancel.Enabled = false;
    }

    /// <summary>
    /// Cancel new record button. Simply call NavigateRecords() method, and restores buttons.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnCancel_Click(object sender, EventArgs e)
    {
        NavigateRecords();

        btnAddNew.Enabled = true;
        btnSave.Enabled = false;
        btnCancel.Enabled = false;
    }

}
}

这是 DBconnection.cs 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SQLtest
{
/// <summary>
/// A class that makes the connection to the SQL Database
/// </summary>
class DBconnection
{
    // variables
    private string sql_string;
    private string strCon;
    System.Data.SqlClient.SqlDataAdapter da_1;

    // set methods
    public string Sql
    {
        set { sql_string = value; }
    }

    public string connection_string
    {
        set { strCon = value; }
    }

    // DataSet
    public System.Data.DataSet GetConnection
    {
        get { return MyDataSet(); }
    }

    // MyDataSet method
    private System.Data.DataSet MyDataSet()
    {
        System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(strCon);
        con.Open();

        da_1 = new System.Data.SqlClient.SqlDataAdapter(sql_string, con);

        System.Data.DataSet dat_set = new System.Data.DataSet();
        da_1.Fill(dat_set,"Table_Data_1");

        con.Close();

        return dat_set;
    }

    // Update DB method
    public void UpdateDB(System.Data.DataSet ds)
    {
        System.Data.SqlClient.SqlCommandBuilder cb = new System.Data.SqlClient.SqlCommandBuilder(da_1);
        cb.DataAdapter.Update(ds.Tables[0]);
    }
}
}

编辑:

为了测试 VS 是否将 DB.mdf 复制到“/bin/Debug”文件夹,我添加了一条新记录,然后从服务器资源管理器中分离 DB,并从“/bin/Debug”文件夹复制 DB.mdf 并替换了 DB。 mdf 在主项目文件夹上。它确认这可能是问题所在,因为现在我可以通过 VS DB Designer 看到新添加的记录。

现在我只需要弄清楚如何在 VS 关闭时将对“/bin/Debug”文件夹中的 DB.mdf 所做的更改更新到主项目 DB.mdf。

【问题讨论】:

    标签: c# sql-server


    【解决方案1】:

    请注意,运行程序会将数据库从根项目文件夹复制到 Release 或 Debug 文件夹,因此每次运行程序时,您都将使用数据库的新副本。这意味着您对数据库所做的任何修改都将在您下次运行应用程序时被覆盖并丢弃。当您只是开发应用程序时,这很好。如果您不希望出现这种情况,请在解决方案资源管理器中选择数据库文件 (.mdf),然后在“属性”窗口中找到“复制到输出目录”选项。如果更新,将其值更改为 Copy。项目根目录中的数据库文件现在只会在输出目录中已存在的文件的较新版本的情况下被复制。

    显然,当您第一次创建解决方案/项目数据库时,它是在项目的父目录中创建的。 之后,当您构建/调试解决方案时,它会将数据库添加到 Bin/Debug 目录中。您在调试时对数据所做的任何更改都在 Debug 数据库中进行。 但是,当您每次在 VS 中运行应用程序时,它会从父目录中提取数据,而该父目录从未收到您在调试时所做的更改,因为这些更改实际上是在 Debug 数据库中进行的。

    解决方案:

    • 在数据库浏览器中
    • 右键单击数据库
    • 选择修改连接
    • 高级选项
    • 搜索属性 AttachDbFileName
    • 将其从调试文件夹 c:...\bin\debug\DB.mdf 更改为 DB
    • 将数据库指向 Debug 目录后,在 VS 服务器资源管理器中,您可以在解决方案资源管理器中删除数据库,所有更新都将在 Debug 数据库中进行。

    【讨论】:

    • 在解决方案资源管理器中选择数据库并将“复制到输出目录”更改为“如果较新则复制”。稍后,当您最终获得最终版本时,将 debug 文件夹中的数据库复制粘贴到您的源文件夹中
    • 我已经在谷歌搜索后做到了这一点,它使我的应用即使在重新启动后也能看到更改,但是在重新启动 VS 时,DB 会清除这些更改。已经尝试将其设置为“不复制”,但它给了我一个错误并且没有连接到数据库。
    • 如果更新选项,请尝试复制并检查。此设置保留在运行时对数据所做的任何更改,这意味着每次运行应用程序并保存对数据的更改时,这些更改在您下次运行应用程序时可见。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多