Inserting values into a mysql database does not work as expected

吃可爱长大的小学妹 提交于 2020-07-10 07:06:24

问题


I try to fill a mySQL/ MariaDB table from within C#. Reading the table and populating a dataset works.

the table structure and its keys etc. are given and cannot be changed:

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);

This is my code to connect to the database, create the sql commands and adapters, and then fill the datasets with the data from the database tables. Then i create a new datarow, fill the columns with values and add this to the DataTable of th DataSet.

    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();
        }
    }

Whereas the manual insert command puts the correct values into the database, the programatic approach via

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

only adds rows with a valid date, but the other columns are NULL.

[Edit #1] : I did some changes to my code, basically I modified the second for loop to insert new data like i did in the first loop. Then the data gets written correctly into the database. But I doubt, if it is a performant way to call .ExecuteNonQuery() several thousand times to put my log file into the database...

[Edit #2] : The 100 000 inserts into the database with .ExecuteNonQuery() are still running after 120 Minutes. This is pretty slow.


回答1:


With MysqlDataAdapter we need to set the selectCommand only. It will generate the insertCommand automatically by MySqlCommandBuilder

Your code is almost correct only 2 changes are required.

1. Add following line before dataAdapterCurrentTest.Update(ds.Tables["currentTest"])

new MySqlCommandBuilder(dataAdapterCurrentTest);


2. Comment folloing line of Code

dataAdapterCurrentTest.InsertCommand=insertCmd

So the final code is

 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();
        }
    }


来源:https://stackoverflow.com/questions/62231021/inserting-values-into-a-mysql-database-does-not-work-as-expected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!