DataAdapter.Update()不会更新数据库

16

我相信这一行代码没有工作的极其简单的原因,但它在过去的一周里一直逃脱了我的注意,所以我希望有人能够注意到我的错误。

我已经在这个项目上工作了几周到一个月的时间。我使用了一些旧的DataAdapter、CommandBuiler等与一些linq to sql编码来操作1个数据库,并且在多个窗口应用程序表单中进行。这个特定的表单使用DataAdapter、Dataset和Command Builder编辑或删除数据库中的行。一直都很好用,直到我换了电脑。现在Dataset正在更新,但是数据库没有更新。

这是这个表单的完整代码:

private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (MessageBox.Show("Exit Cook Book?", "Exit?", MessageBoxButtons.OKCancel) == DialogResult.OK)
    {
        Application.Exit();
    }
}

private void goBackToolStripMenuItem_Click(object sender, EventArgs e)
{
    AddRecipe goBack = new AddRecipe();

    Close();
    goBack.Show();
}

private void helpToolStripMenuItem_Click(object sender, EventArgs e)
{
    MessageBox.Show("Scan through the Cook Book to find recipes that you wish to edit or delete.", "Help!");
}

SqlConnection con;
SqlDataAdapter dataAdapt;
DataSet dataRecipe;
SqlCommandBuilder cb;

int MaxRows = 0;
int inc = 0;


private void EditRecipe_Load(object sender, EventArgs e)
{
    con = new SqlConnection();
    dataRecipe = new DataSet();

    con.ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Recipes.mdf;Integrated Security=True;User Instance=True";

        con.Open();

        //MessageBox.Show("Database Open");

        string sql = "SELECT* From CookBookRecipes";
        dataAdapt = new SqlDataAdapter(sql, con);

        dataAdapt.Fill(dataRecipe, "CookBookRecipes");
        NavigateRecords();
        MaxRows = dataRecipe.Tables["CookBookRecipes"].Rows.Count;

        con.Close();
}


private void NavigateRecords()
{
    DataRow dRow = dataRecipe.Tables["CookBookRecipes"].Rows[inc];

    tbRName.Text = dRow.ItemArray.GetValue(0).ToString();
    listBox1.SelectedItem = dRow.ItemArray.GetValue(1).ToString();
    tbRCreate.Text = dRow.ItemArray.GetValue(2).ToString();
    tbRIngredient.Text = dRow.ItemArray.GetValue(3).ToString();
    tbRPrep.Text = dRow.ItemArray.GetValue(4).ToString();
    tbRCook.Text = dRow.ItemArray.GetValue(5).ToString();
    tbRDirections.Text = dRow.ItemArray.GetValue(6).ToString();
    tbRYield.Text = dRow.ItemArray.GetValue(7).ToString();
    textBox1.Text = dRow.ItemArray.GetValue(8).ToString();
}

private void btnNext_Click(object sender, EventArgs e)
{
    if (inc != MaxRows - 1)
    {
        inc++;
        NavigateRecords();
    }
    else
    {
        MessageBox.Show("That's the last recipe of your Cook Book!", "End");
    }
}

private void btnBack_Click(object sender, EventArgs e)
{
    if (inc > 0)
    {
        inc--;
        NavigateRecords();
    }
    else
    {
        MessageBox.Show("This is the first recipe of your Cook Book!", "Start");
    }
}

private void btnSave_Click(object sender, EventArgs e)
{
    cb = new SqlCommandBuilder(dataAdapt);

    DataRow daRow = dataRecipe.Tables["CookBookRecipes"].Rows[inc];

    daRow[0] = tbRName.Text;
    daRow[1] = listBox1.SelectedItem.ToString();
    daRow[2] = tbRCreate.Text;
    daRow[3] = tbRIngredient.Text;
    daRow[4] = tbRPrep.Text;
    daRow[5] = tbRCook.Text;
    daRow[6] = tbRDirections.Text;
    daRow[7] = tbRYield.Text;
    daRow[8] = textBox1.Text;

    if (MessageBox.Show("You wish to save your updates?", "Save Updates?", MessageBoxButtons.OKCancel) == DialogResult.OK)
    {

        dataAdapt.Update(dataRecipe, "CookBookRecipes");

        MessageBox.Show("Recipe Updated", "Update");
    }
}

private void btnDelete_Click(object sender, EventArgs e)
{
    SqlCommandBuilder cb;
    cb = new SqlCommandBuilder(dataAdapt);

    if (MessageBox.Show("You wish to DELETE this recipe?", "Delete?", MessageBoxButtons.OKCancel) == DialogResult.OK)
    {
        dataRecipe.Tables["CookBookRecipes"].Rows[inc].Delete();
        MaxRows--;
        inc = 0;
        NavigateRecords();

        dataAdapt.Update(dataRecipe, "CookBookRecipes");

        MessageBox.Show("Your Recipe has been Deleted", "Delete");
    }
}

这应该更新表格:

dataAdapt.Update(dataRecipe, "CookBookRecipes");

我没有收到任何错误提示,但是数据表格就是无法更新。

先感谢您的帮助,如果您需要更多信息,请让我知道。


你有没有得到这个问题的答案?我正在使用一个处理我的数据库更新的项目,遇到了同样的问题。在一个项目中使用它时,就像你所说的那样失败了。但在另一个项目中使用它却可以正常工作。所以我真的很困惑。我甚至比较了两个SqlAdapter.GetUpdateCommand().CommandText以及ItemArray数据元素,它们完全相同。虽然自动生成的INSERT命令中有许多参数,但我并不真正理解。RowStates也是一样的。真是令人沮丧。 - B H
10个回答

13

为了更新数据库中的数据,您的SqlDataAdapter需要设置其InsertCommand、UpdateCommand和DeleteCommand属性。您创建的SqlCommandBuilder实例具有这些命令,但您需要将它们设置为您的SqlDataAdapter。

换句话说:

 SqlCommandBuilder cb;
 cb = new SqlCommandBuilder(dataAdapt);

并且

 dataAdapt.Update(dataRecipe, "CookBookRecipes");

你需要

dataAdapt.DeleteCommand = cb.GetDeleteCommand(true);
dataAdapt.UpdateCommand = cb.GetUpdateCommand(true);
dataAdapt.InsertCommand = cb.GetInsertCommand(true);

3
搜遍了所有信息,没有人提到将命令生成器生成的查询绑定到数据适配器。感谢这个提示。 - Ajibola
2
请注意,如果在创建SqlCommandBuilder时指定了dataAdaptor,则无需设置命令,SqlCommandBuilder会将自己注册为侦听器。文档 - nicV

2

SqlText?我应该把它放在哪里? - Miffed

1
尝试以下源代码。
private void btnSave_Click(object sender, EventArgs e)
{
    cb = new SqlCommandBuilder(dataAdapt);

    //Old source: DataRow daRow = dataRecipe.Tables["CookBookRecipes"].Rows[inc];

    //Added source code
    DataRow daRow = dataRecipe.Tables["CookBookRecipes"].NewRow();

    //Added source code
    dataRecipe.Tables["CookBookRecipes"].AddRow(daRow);

    daRow.BeginEdit();
    daRow[0] = tbRName.Text;
    daRow[1] = listBox1.SelectedItem.ToString();
    daRow[2] = tbRCreate.Text;
    daRow[3] = tbRIngredient.Text;
    daRow[4] = tbRPrep.Text;
    daRow[5] = tbRCook.Text;
    daRow[6] = tbRDirections.Text;
    daRow[7] = tbRYield.Text;
    daRow[8] = textBox1.Text;
    daRow.EndEdit();

    //Reset state of rows to unchanged
    dataRecipe.Tables["CookBookRecipes"].AcceptChanges();
    //Set modified. The dataAdapt will call update stored procedured 
    //for the row that has Modifed row state. 
    //You can also try SetAdded() method for new row you want to insert
    daRow.SetModified();

    if (MessageBox.Show("You wish to save your updates?", "Save Updates?", MessageBoxButtons.OKCancel) == DialogResult.OK)
    {

        dataAdapt.Update(dataRecipe, "CookBookRecipes");

        MessageBox.Show("Recipe Updated", "Update");
    }
}

我偶尔需要使用批量更新,并且总是忘记将行标记为已修改。这正是所需的,谢谢您的提醒。 - dyslexicanaboko

1
在更新之前添加AcceptChangesDuringUpdate对我有用,例如:
foreach (string tableName in tableNames)
        {             
            da = new SqlDataAdapter("SELECT * FROM " + tableName, cn);
            cb = new SqlCommandBuilder(da); //initialise the update, insert and delete commands of da
            da.AcceptChangesDuringUpdate = true;
            da.Update(myDataSet, tableName);               
        }

0

如果您正在使用Local-DB,请检查您的数据库属性。

在“复制到输出目录”属性中设置值为“仅在较新时复制”,然后您就可以开始了。


0

我遇到了相同的问题:用一些新行填充了一个新数据集,但在更新时没有发生任何事情。我使用了与 MySqlDataAdapter 类似的东西。

结果发现,当您需要从 MySqlCommandBuilder 获取 InsertCommand 时,必须将行状态指定为已添加。请参见:MSDN


0
如果您使用的数据库已添加到项目中,则其“复制到输出目录”属性可能设置为“始终复制”。
如果是这样,请尝试将其更改为“仅在更新时复制”。
我从这里获得了解决方案。

0

我遇到了同样的问题。我的dataadapter.fill可以正常工作,但是dataadapter.update却无法正常工作。我意识到问题出在我的数据库表中没有包含主键。当我修改我的表以包含一个带有主键的列时,dataadapter.fill就可以正常工作了。 希望这能帮助到某些人。


0
//change this line

DataRow daRow = dataRecipe.Tables["CookBookRecipes"].NewRow();

daRow[0] = tbRName.Text;
daRow[1] = listBox1.SelectedItem.ToString();
daRow[2] = tbRCreate.Text;
daRow[3] = tbRIngredient.Text;
daRow[4] = tbRPrep.Text;
daRow[5] = tbRCook.Text;
daRow[6] = tbRDirections.Text;
daRow[7] = tbRYield.Text;
daRow[8] = textBox1.Text;

if (MessageBox.Show("You wish to save your updates?", "Save Updates?", MessageBoxButtons.OKCancel) == DialogResult.OK)
{
//add & change this too
dataRecipe.Tables["CookBookRecipes"].Rows.Add(daRow);
    dataAdapt.Update(dataRecipe, "CookBookRecipes");

    MessageBox.Show("Recipe Updated", "Update");
}

}


0

你可能需要

DataAdapeter.AcceptChanges()

1
DataAdapter没有AcepptChanges()方法。实际上,如果您从_DataSet_中调用该方法,调用DataAdapter.Update()方法之前,您将设置所有行状态为_Unchanged_并防止DataAdapter.Update()在修改的行中搜索标志,因此,防止该方法选择适当的INSERT、UPDATE、DELETE命令。 - David Martinez C.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接