OleDbCommandBuilder 更新 - 至少缺少一个参数值

OleDbCommandBuilder Update - at least one parameter values are missing

我做了什么: 我正在使用 OleDbAdapter 从数据库中读取数据,填充一个新的 DataTable。这很顺利。然后我想在该 DataTable 中添加一列,这也很顺利。

我添加了一个 OleDbCommandBuilder,以使用多一列的 DataTable 更新数据库。我用 OleDbCommandBuilder 的 'automatical way' 进行了尝试,因为我认为我想要的很简单。但到目前为止,这还没有奏效。

我期待的 是 OleDbCommandBuilder 正在为我编写一个新的 SQL 命令,其中包含 'UPDATE' 或 'INSERT'。我进一步预计,我无法读取 OleDbAdapter 中的所有命令,SELECT 命令除外,因为 OleDbAdapter 在使用它们之前从构建器获取命令。

我在互联网上看到,如果我调用 adapter.Update(...),则不需要 adapter.Fill(...)。但是没有 adapter.Fill(...) 我无法从数据库中获取内容。

终于有个问题有了名字:

现在,在搜索问题后,我得到以下消息:System.Data.OleDbException:至少有一个参数没有给出值。

我的问题:

1) 我是不是觉得有什么不对?

2) 哪个参数没有值? 已解决 这帮助我理解了: https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?redirectedfrom=MSDN&view=netframework-4.7.2#System_Data_SqlClient_SqlCommand_Parameters

3) adapter, builder ... 的顺序是否正确?

4) 我还有其他事情要做吗,比如调用一个函数来使用适配器更新 SQL 命令?

5) 我如何改进解决该问题的方法?例如:是否有任何事件可以帮助我更多地了解正在发生的事情?如何捕捉这样的事件?

非常感谢!

这是我的代码——原来它分为两个函数。但我为你把它全部放在一起:

  public virtual bool AddColumnOfString_ToDataTable(string tableName, string newColumnName, string defaultCellValue)
    {
       /// Approach: Accessing database at minimum time.
       ///    returns true if  column name could not be found and column could be added

        DataTable table = new DataTable();
        string strSQL = "SELECT " + tableName;
        OleDbDataAdapter adapter = new OleDbDataAdapter(strSQL, strConnection);
        adapter.Fill(table);     
        OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);

        bool result = false;

        if (false == HasColumn(newColumnName))
        {
            DataColumn newColumn = new DataColumn(newColumnName, typeof(System.String));
            newColumn.DefaultValue = defaultCellValue;
            table.Columns.Add(newColumn);
            result = true;
        }

        adapter.Update(table);

        return result;
    }

您通过向数据添加新列修改了 DataTable 的结构table,这没有反映在生成的 update/insert/delete sql 命令中。

看看这个例子:OleDbCommandBuilder Class

如此简单:

   adapter.Update(table);

仅更新​​服务器中table库中的数据(如果更改)

1) Do I expect something wrong?

不,它在工作,但在 MS access 中 table 的基础结构没有变化

2) Which parameter hasn't got a value?

你没有在 SQL 命令中传递参数

3) Are the adapter, builder ... placed in the right order?

是的,但删除了修改数据的部分table。没有效果

4) Have I got something additional to do, like calling a function to update the SQL command withing the adapter?

查看我的代码和评论。

5) How can I improve the way I solve that problem? E.g.: Is there any event which will help me to understand more what is going on? How to catch such an event?

您不能通过添加新列

来修改数据的结构table

更新

我测试了你的代码,修改了注释:

       public  bool AddColumnOfString_ToDataTable(string tableName, string newColumnName, string defaultCellValue)
            {
                // Approach: Accessing database at minimum time.
                //    returns true if  column name could not be found and column could be added

                DataTable table = new DataTable();


                //string strSQL = "SELECT " + tableName; // not valid syntax
                string strSQL = "SELECT * from " + tableName;
                OleDbDataAdapter adapter = new OleDbDataAdapter(strSQL, myConnectionString);
                adapter.Fill(table);
                OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);

                bool result = false;
                // remove this code, it has no effect on the underlying base table in MS Access databas
                //any change in the structure of datatable has no effect on the database

                /*
                if (false == table.HasColumn(newColumnName))
                {
                    DataColumn newColumn = new DataColumn(newColumnName, typeof(System.String));
                    newColumn.DefaultValue = defaultCellValue;
                    table.Columns.Add(newColumn);
                    result = true;
                }
                */

                //  code to modify data in DataTable here

                //Without the OleDbCommandBuilder this line would fail
                adapter.Update(table);

                //just to review the generated code                 
                Console.WriteLine(builder.GetUpdateCommand().CommandText);
                Console.WriteLine(builder.GetInsertCommand().CommandText);
                return result;
            }

更新2:

如果您有兴趣向 MS Access 数据库添加新列,您可以运行以下代码:

 public   bool AddColumn(OleDbConnection con, 
                string tableName,string colName,string colType, object defaultValue)
            {
                string query = $"ALTER TABLE {tableName}  ADD COLUMN {colName} {colType} DEFAULT {defaultValue} ";
                var cmd = new OleDbCommand(query, con);
                try
                {
                    con.Open();
                    cmd.ExecuteNonQuery();
                    Console.WriteLine("Sql Executed Successfully");
                    return true;
                }
                catch (OleDbException e)
                {
                    Console.WriteLine("Error Details: " + e);
                }
                finally
                {
                    Console.WriteLine("closing conn");
                    con.Close();
                }
                return false;
            }

      public   void AddColumnTest()
            {
                OleDbConnection con = new OleDbConnection(myConnectionString);
                string tableName="table1";
                string colName="country";
                string colType="text (30)";
                object defaultValue = "USA";
                AddColumn(con, tableName, colName, colType, defaultValue);
            }               

我用 MS Access 测试了代码,它工作正常。