问题
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