【问题标题】:Inserting values into a mysql database does not work as expected将值插入 mysql 数据库无法按预期工作
【发布时间】:2020-09-25 14:03:35
【问题描述】:

我尝试从 C# 中填充 mySQL/MariaDB 表。读取表格并填充数据集是可行的。

表结构及其键等已给定且不能更改:

CREATE TABLE `fhem`.`history` (TIMESTAMP TIMESTAMP, DEVICE varchar(32), TYPE varchar(32), EVENT varchar(512), READING varchar(32), VALUE varchar(32), UNIT varchar(32));
CREATE TABLE `fhem`.`current` (TIMESTAMP TIMESTAMP, DEVICE varchar(32), TYPE varchar(32), EVENT varchar(512), READING varchar(32), VALUE varchar(32), UNIT varchar(32));
CREATE INDEX Search_Idx ON `fhem`.`history` (DEVICE, READING, TIMESTAMP);

这是我连接到数据库的代码,创建 sql 命令和适配器,然后用数据库表中的数据填充数据集。 然后我创建一个新的数据行,用值填充列并将其添加到数据集的数据表中。

    class Program
    {
        static void Main(string[] args)
        {
            MySqlConnectionStringBuilder connBuilder = new MySqlConnectionStringBuilder();

            connBuilder.Server = "ds2";
            connBuilder.Database = "fhem";
            connBuilder.UserID = "fhemdbuser";
            connBuilder.Port = 3307;
            connBuilder.Password = "!2345Abcde";
            //connBuilder.DefaultCommandTimeout = 120;
            //connBuilder.UseDefaultCommandTimeoutForEF = true;
            //connBuilder.AllowUserVariables = true;

            MySqlConnection conn = new MySqlConnection(connBuilder.ConnectionString);
            conn.Open();
            MySqlCommand selectCmdCurrent = new MySqlCommand("select `TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT` from current;", conn);
            MySqlCommand selectCmdCurrentTest = new MySqlCommand("select `TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT` from currentTest;", conn);
            MySqlCommand updateCmd = new MySqlCommand("update `currentTest` set `TIMESTAMP`=@p1,`DEVICE`=@p2,`TYPE`=@p3,`EVENT`=@p4,`READING`=@p5,`VALUE`=@p6,`UNIT`=@p7", conn);
            updateCmd.Parameters.Add("@p1", MySql.Data.MySqlClient.MySqlDbType.DateTime);
            updateCmd.Parameters.Add("@p2", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            updateCmd.Parameters.Add("@p3", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            updateCmd.Parameters.Add("@p4", MySql.Data.MySqlClient.MySqlDbType.VarString, 512);
            updateCmd.Parameters.Add("@p5", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            updateCmd.Parameters.Add("@p6", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            updateCmd.Parameters.Add("@p7", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);

            MySqlCommand insertCmd = new MySqlCommand("insert into `currentTest` values(@p1, @p2, @p3, @p4, @p5, @p6, @p7)", conn);
            insertCmd.Parameters.Add("@p1", MySql.Data.MySqlClient.MySqlDbType.DateTime);
            insertCmd.Parameters.Add("@p2", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            insertCmd.Parameters.Add("@p3", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            insertCmd.Parameters.Add("@p4", MySql.Data.MySqlClient.MySqlDbType.VarString, 512);
            insertCmd.Parameters.Add("@p5", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            insertCmd.Parameters.Add("@p6", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            insertCmd.Parameters.Add("@p7", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            MySqlDataAdapter dataAdapterCurrent = new MySqlDataAdapter(selectCmdCurrent);
            MySqlDataAdapter dataAdapterCurrentTest = new MySqlDataAdapter(selectCmdCurrentTest);
            // MySqlCommandBuilder builder = new MySqlCommandBuilder(dataAdapterCurrent);
            dataAdapterCurrentTest.InsertCommand = insertCmd;
            dataAdapterCurrentTest.UpdateCommand = updateCmd;
            DataSet ds = new DataSet();
            MySqlCommand prepareCmd = new MySqlCommand("truncate currentTest;", conn);
            prepareCmd.ExecuteNonQuery();
            //prepareCmd = new MySqlCommand("insert into currentTest select * from current;", conn);
            //prepareCmd.ExecuteNonQuery();
            prepareCmd = new MySqlCommand("INSERT INTO `currentTest` VALUES(\"2020-06-06 12:45:23\",\"DEVICE\", \"TYPE\", \"EVENT\", \"READING\", \"VALUE\", \"UNIT\")", conn);
            for (int i = 0; i < 10; i++)
                prepareCmd.ExecuteNonQuery();
            dataAdapterCurrentTest.Fill(ds, "currentTest");
            dataAdapterCurrent.Fill(ds, "current");
            int row = 0;

            Stopwatch sw = new Stopwatch();
            for (int i = 0; i < 10; i++)
            {

                DataRow newrow = ds.Tables["currentTest"].NewRow();
                newrow["Timestamp"] = DateTime.Now;
                newrow["Device"] = "Device";
                newrow["TYPE"] = "Type";
                newrow["EVENT"] = "Event";
                newrow["READING"] = "Reading";
                newrow["VALUE"] = "Value";
                newrow["UNIT"] = "Unit";
                ds.Tables["currentTest"].Rows.Add(newrow);
            }
            dataAdapterCurrentTest.Update(ds.Tables["currentTest"]);
            ds.Tables["currentTest"].AcceptChanges();
        }
    }

手动插入命令将正确的值放入数据库,而编程方法通过

DataRow newrow = ds.Tables["currentTest"].NewRow();
ds.Tables["currentTest"].Rows.Add(newrow);
dataAdapterCurrentTest.Update(ds.Tables["currentTest"]);
ds.Tables["currentTest"].AcceptChanges();

仅添加具有有效日期的行,但其他列为 NULL。

[编辑#1]: 我对我的代码做了一些更改,基本上我修改了第二个 for 循环以插入新数据,就像我在第一个循环中所做的那样。然后数据被正确写入数据库。但我怀疑,调用.ExecuteNonQuery() 数千次以将我的日志文件放入数据库是否是一种高效的方式......

[编辑#2]: 120 分钟后,使用.ExecuteNonQuery() 向数据库中的 100 000 次插入仍在运行。这很慢。

【问题讨论】:

  • 在每种情况下,请确定您的 PRIMARY KEY
  • 在“程序化方法”中,您创建了一个新的数据行,但没有给它任何值。那是实际代码还是只是精简版?顺便说一句,您不需要调用 AcceptChanges(),调用 Update() 会将所有行标记为未修改。
  • @Crowcoder:实际代码在上面的大代码部分,下面的小代码示例只是总结了动作......
  • @Strawberry:正如我在问题中所说,表格及其索引无法更改。我只有这个架构。如果我正确理解 FHEM 服务器,则行中的每一列都计入主键,因为在任何给定的时间戳,任何数量的设备都可以创建一个特定的事件,然后导致具体的读数、值和单位......跨度>
  • 所以。有什么独特之处?

标签: c# mysql dataadapter


【解决方案1】:

使用 MysqlDataAdapter,我们只需要设置 selectCommand。它将由MySqlCommandBuilder自动生成insertCommand

您的代码几乎是正确的,只需要进行 2 处更改。

1。在dataAdapterCurrentTest.Update(ds.Tables["currentTest"])之前添加以下行

new MySqlCommandBuilder(dataAdapterCurrentTest);


2.注释下面的代码行

dataAdapterCurrentTest.InsertCommand=insertCmd

所以最终的代码是

 class Program
    {
        static void Main(string[] args)
        {
            MySqlConnectionStringBuilder connBuilder = new MySqlConnectionStringBuilder();

            connBuilder.Server = "ds2";
            connBuilder.Database = "fhem";
            connBuilder.UserID = "fhemdbuser";
            connBuilder.Port = 3307;
            connBuilder.Password = "!2345Abcde";
            //connBuilder.DefaultCommandTimeout = 120;
            //connBuilder.UseDefaultCommandTimeoutForEF = true;
            //connBuilder.AllowUserVariables = true;

            MySqlConnection conn = new MySqlConnection(connBuilder.ConnectionString);
            conn.Open();
            MySqlCommand selectCmdCurrent = new MySqlCommand("select `TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT` from current;", conn);
            MySqlCommand selectCmdCurrentTest = new MySqlCommand("select `TIMESTAMP`, `DEVICE`, `TYPE`, `EVENT`, `READING`, `VALUE`, `UNIT` from currentTest;", conn);
            MySqlCommand updateCmd = new MySqlCommand("update `currentTest` set `TIMESTAMP`=@p1,`DEVICE`=@p2,`TYPE`=@p3,`EVENT`=@p4,`READING`=@p5,`VALUE`=@p6,`UNIT`=@p7", conn);
            updateCmd.Parameters.Add("@p1", MySql.Data.MySqlClient.MySqlDbType.DateTime);
            updateCmd.Parameters.Add("@p2", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            updateCmd.Parameters.Add("@p3", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            updateCmd.Parameters.Add("@p4", MySql.Data.MySqlClient.MySqlDbType.VarString, 512);
            updateCmd.Parameters.Add("@p5", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            updateCmd.Parameters.Add("@p6", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            updateCmd.Parameters.Add("@p7", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);

            MySqlCommand insertCmd = new MySqlCommand("insert into `currentTest` values(@p1, @p2, @p3, @p4, @p5, @p6, @p7)", conn);
            insertCmd.Parameters.Add("@p1", MySql.Data.MySqlClient.MySqlDbType.DateTime);
            insertCmd.Parameters.Add("@p2", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            insertCmd.Parameters.Add("@p3", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            insertCmd.Parameters.Add("@p4", MySql.Data.MySqlClient.MySqlDbType.VarString, 512);
            insertCmd.Parameters.Add("@p5", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            insertCmd.Parameters.Add("@p6", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            insertCmd.Parameters.Add("@p7", MySql.Data.MySqlClient.MySqlDbType.VarString, 128);
            MySqlDataAdapter dataAdapterCurrent = new MySqlDataAdapter(selectCmdCurrent);
            MySqlDataAdapter dataAdapterCurrentTest = new MySqlDataAdapter(selectCmdCurrentTest);
            // MySqlCommandBuilder builder = new MySqlCommandBuilder(dataAdapterCurrent);
           // dataAdapterCurrentTest.InsertCommand = insertCmd;
            dataAdapterCurrentTest.UpdateCommand = updateCmd;
            DataSet ds = new DataSet();
            MySqlCommand prepareCmd = new MySqlCommand("truncate currentTest;", conn);
            prepareCmd.ExecuteNonQuery();
            //prepareCmd = new MySqlCommand("insert into currentTest select * from current;", conn);
            //prepareCmd.ExecuteNonQuery();
            prepareCmd = new MySqlCommand("INSERT INTO `currentTest` VALUES(\"2020-06-06 12:45:23\",\"DEVICE\", \"TYPE\", \"EVENT\", \"READING\", \"VALUE\", \"UNIT\")", conn);
            for (int i = 0; i < 10; i++)
                prepareCmd.ExecuteNonQuery();
            dataAdapterCurrentTest.Fill(ds, "currentTest");
            dataAdapterCurrent.Fill(ds, "current");
            int row = 0;

            Stopwatch sw = new Stopwatch();
            for (int i = 0; i < 10; i++)
            {

                DataRow newrow = ds.Tables["currentTest"].NewRow();
                newrow["Timestamp"] = DateTime.Now;
                newrow["Device"] = "Device";
                newrow["TYPE"] = "Type";
                newrow["EVENT"] = "Event";
                newrow["READING"] = "Reading";
                newrow["VALUE"] = "Value";
                newrow["UNIT"] = "Unit";
                ds.Tables["currentTest"].Rows.Add(newrow);
            }

            new MySqlCommandBuilder(dataAdapterCurrentTest);

            dataAdapterCurrentTest.Update(ds.Tables["currentTest"]);
            ds.Tables["currentTest"].AcceptChanges();
        }
    }

【讨论】:

  • 我也试过这个,甚至在使用参数化命令之前。也不行。
  • 我已将代码上传到wowogiengen.de/MySqLTest.zip
  • 但它对我有用。使用您的代码,它添加了 20 行,其中最后 10 行仅插入了时间戳。但使用我的代码,它会插入整行
  • 我建议,在 VS 中创建新的控制台项目,将我的代码复制到 main 函数中,添加引用并运行代码你会得到清晰的。请在执行之前检查 SQL。然后更新您的代码。它肯定会起作用。您的代码与我在这里纠正的问题相同。请仔细阅读答案“无需为数据适配器定义单独的插入命令”
  • Mea culpa :-) 你是对的,现在它似乎起作用了。 20行数据,其中10行大写,另外10行混合大小写:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-02
相关资源
最近更新 更多