MySqlDataAdapter UpdateCommand not recognizing primary key - c#

I am using a temporary table to display data in a datagridview. When the data in the datagridview is edited, I am trying to update the temporary table. This is the code inside the dataGridView1_RowValidated method that I'm using to do so:
MySqlDataAdapter adapter = new MySqlDataAdapter("select * from all_plants_temp", con);
MySqlCommandBuilder builder = new MySqlCommandBuilder(adapter);
adapter.UpdateCommand = builder.GetUpdateCommand();
adapter.Update(changes);
((DataTable)dataGridView1.DataSource).AcceptChanges();
However, I am running into the following error whenever I leave the edited row:
Dynamic SQL generation for the UpdateCommand is not supported against a SelectCommand that does not return any key column information.
From what the error suggests (along with every website I visited), I need to include a primary key in the table. However, I already have an int auto-incrementing primary key. This is the code that I used to create the temporary table, along with the relevant code of the original non-temporary table.
ALTER TABLE all_plants ADD COLUMN plantID INT PRIMARY KEY AUTO_INCREMENT;
CREATE TEMPORARY TABLE all_plants_temp SELECT * FROM all_plants;
Can someone tell me the fault in my code? Any help is appreciated.

As said before I belive your temporary table does not have a primary key.
Try using this query. It will create the temporary table with a Primary Key. Change YourPk with what you want.
CREATE TEMPORARY TABLE all_plants_temp
(YourPk int(10) NOT NULL, PRIMARY KEY (YourPk)) SELECT * from all_plants;

Related

Problem with database connection C# from System.Data.SqlClient

I have looked at all the similar questions on this topic but none seem to work for me.
When I try to run my application, I get the following error:
System.Data.SqlClient.SqlException: 'Cannot insert the value NULL into column 'Id', table 'C:\FINALLY\DATABASE.MDF.dbo.loginTB'; column does not allow nulls. INSERT fails.
Here is my code:
private void btnContinued_reg_Click(object sender, EventArgs e)
{
SqlConnection cn = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\finally\DataBase.mdf;Integrated Security=True;Connect Timeout=30");
SqlCommand cmd= new SqlCommand("insert into loginTB(username,password)values('" + txtUserName_reg.Text + "','" + txtPaswword_reg.Text + "')",cn);
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
MessageBox.Show("good");
}
What am I doing wrong?
A snapshot of my code:
The problem does not indicate a connection problem at all. It seems that you are trying to insert a record into a table, and you are trying to pass null as the id, which gives you the error.
My guess would be the error is in the definition of that table loginTB, you make sure the column id has the property IDENTITY, since you are using SQL Server.
An example would be like this:
CREATE TABLE new_employees
(
id_num int PRIMARY KEY IDENTITY(1,1),
fname varchar (20),
minit char(1),
lname varchar(30)
);
Identity columns can be used for generating key values. The identity property on a column guarantees the following:
Each new value is generated based on the current seed & increment.
Each new value for a particular transaction is different from other concurrent transactions on the table.
The identity property on a column does not guarantee the following:
Uniqueness of the value
Uniqueness must be enforced by using a PRIMARY KEY or UNIQUE constraint or UNIQUE index.
Follow up answer of previous answers.
If you already created a table and want to modify it to work correctly:
Go to the table properties from SSMS tool and select the identity column and save the properties. Identity column must be marked as not nullable.

Changing Auto Increment of a colum in SQLite

I am creating a table that at first keyID column is NOT in AUTO INCREMENT since i am going to insert a data that came from an old database where the keyID is already been set to each rows and it's not possible to be changed. So is it possible that i can set the column to AUTO INCREMENT after all the data has been moved? I've seen this:
ALTER TABLE tbl_name MODIFY COLUMN keyID_id INT auto_increment
So if ever i set the keyID to auto increment after i moved all the data, so for example 10 rows has been transferred and some numbers may be missing for example, keyIDs: 1,2,3,5,6,7...15
can I assume that after i set the keyID to auto increment, the next row will be keyID 16?
The first thing to say here is that SQLite has no syntax to change the settings of a column. You are forced to rename your original table, create a new table with the schema you want and then copy from the renamed table into the new one.
So your code to add the AUTOINCREMENT flag to your table is something like this
SQLiteCommand cmd = new SQLiteCommand();
cmd.Connection = yourConnection;
cmd.CommandText = "ALTER TABLE tblName RENAME TO tmp_tblName";
cmd.ExecuteNonQuery();
cmd = new SQLiteCommand(#"
CREATE TABLE tblName
(ID INTEGER PRIMARY KEY AUTOINCREMENT,
AnotherField NVARCHAR(100) NOT NULL)", cnn);
cmd.ExecuteNonQuery();
cmd.CommandText = "INSERT INTO tblName (ID, AnotherField) SELECT ID, AnotherField FROM tmp_tblName";
cmd.ExecuteNonQuery();
Now, when you create a table with the AUTOINCREMENT SQLite add a new row to an internal table called sqlite_sequence. This table could be read by the usual ADO.NET classes
cmd.CommandText = "SELECT seq FROM sqlite_sequence WHERE name = 'tblName'";
int lastInsertedValue = Convert.ToInt32(cmd.ExecuteScalar());
Console.WriteLine(lastInsertedValue);
If your run this test code you will see that the value for the field seq is equal to the maximum value inserted in the PRIMARY KEY field.
After this if you try to insert a new record in your table you will see that the AUTOINCREMENT flag has started to work as expected and your new record will receive the next value from the sequence....
Even though the SQLite documentation and some posts state that the alter table command in SQLite is very limited and should not allow making such modifications, it seems that it's still possible to alter PK properties. What worked for me was:
Create a table with CREATE TABLE "test" (Field1INTEGER,Field2TEXT,)
Insert arbitrary data
Change column definition for column Field1 with DB Browser for SQLite
Subsequent inserts should then auto increment the IDs in the column Field1.
I must admit that it might not be suitable if there's the requirement to do this programatically, but if some manual steps are acceptable, it may be a solution.

Bulk Insert With Auto Increment - No Identity column

I am trying to implement bulk insert of data from Datatable. In my MS-SQL Table(Destination table) i have a column with primary key not Identity column, so i have to increment manually. But its not possible in Code because there will be multi Thread on the same table.Please give me suggestion if any.
public void BulkInsert(DataTable dtTable)
{
DataTable dtProductSold = dtTable;
//creating object of SqlBulkCopy
SqlBulkCopy objbulk = new SqlBulkCopy(ConStr.ToString());
//assigning Destination table name
objbulk.DestinationTableName = "BatchData_InvReportMapping";
//Mapping Table column
objbulk.ColumnMappings.Add("InvPK", "InvPK");
objbulk.ColumnMappings.Add("DateValue", "DateDalue");
objbulk.ColumnMappings.Add("TextValue", "TextValue");
objbulk.ColumnMappings.Add("NumericValue", "NumericValue");
objbulk.ColumnMappings.Add("ErrorValue", "ErrorValue");
//inserting bulk Records into DataBase
objbulk.WriteToServer(dtProductSold);
}
Thanks in advance,
This is too long for a comment.
If you have a primary key column, then you need to take responsibility for its being unique and non-NULL when you insert rows. SQL Server offers a very handy mechanism to help with this, which is the identity column.
If you do not have an identity, then I you basically have two options:
Load data that has a valid primary key column.
Create a trigger that assigns the value when rows are loaded in.
Oh, wait. The default option for bulk insert is not to fire triggers, so the second choice really isn't a good option.
Instead, modify the table to have an identity primary key column. Then define a view on the table without the primary key and do the bulk insert into the view. The primary key will then be assigned automatically.
EDIT:
There is a third option, which might be feasible. Load the data into a staging table. Then insert from the staging table into the final table, calculating the primary key value. Something like this:
insert into finaltable (pk, . . .)
select m.maxpk + seqnum, . . . .
from (select row_number() over (order by (select null)) as seqnum,
. . .
from stagingtable
) s cross join
(select max(pk) as maxpk
from finaltable
) m;
i had one idea
generally we use tables to store the records, even if you insert the data using front end finally it will be stored in table.So i am suggesting to use sequences with insert trigger on the table. which means when you insert the data into the table first the trigger will be called, sequence will be incremented the the increased value will be stored along with other values in the table. just try this. because in oracle 11g we don't have identity() hence we will use sequences and insert trigger for identity column
Create a Table called id's. VARCHAR(50) TableName, INT Id.
When you want to generate your ids read the relevant row and increment it by the number of rows you want to insert within the same transaction.
you can now bulk insert these rows whenever you want without worrying about other threads inserting them.
Similar to how Nhibernates HiLow generator works.
http://weblogs.asp.net/ricardoperes/making-better-use-of-the-nhibernate-hilo-generator

Double records in result set

I have found a strange phenomena on MSSQL server.
Let say we have a table:
CREATE TABLE [testTable]
(
[ID] [numeric](11, 0) NOT NULL,
[Updated] [datetime] NULL,
PRIMARY KEY (ID)
);
I do a simple select based on Updated field:
SELECT TOP 10000 ID, Updated
FROM testTable
WHERE Updated>='2013-05-22 08:55:12.152'
ORDER BY Updated
And now comes the fun part: how can I have in result set double records - I mean same ID in 2 records with different Updated value.
For me it seems to be, that the Updated datetime value was changed and it was included one more time in result set. But is it possible?
UPDATE:
Source code I using for downloading data from SQL server:
using (SqlCommand cmd = new SqlCommand(sql, Connection) { CommandTimeout = commandTimeout })
{
using (System.Data.SqlClient.SqlDataAdapter adapter = new System.Data.SqlClient.SqlDataAdapter(cmd))
{
DataTable retVal = new DataTable();
adapter.Fill(retVal);
return retVal;
}
}
Connection = SqlConnection
sql = "SELECT TOP 10000 ...."
Your question seems to lack some details but here's my ideas.
The first case I'd think of would be that you are somehow selecting those IDs twice (could be a join, group by, ...). Please manually check inside your table (in MSSQL Server rather than inside a function or method) to see if there is dupplicated IDs. If there is, the issue is that your Primary Key hasn't been set correctly. Otherwise, you will need to provide all the relevant code that is used to select the data in order to get more help.
Another case might be that someone or something altered the primary key so it is on both ID and Updated, allowing the same ID to be inserted twice as long as the Updated field doesn't match too.
You may also try this query to see if it gets dupplicated IDs inside your context:
SELECT ID
from testTable
ORDER BY ID
I hope this helps.

Why does a typed dataset cause an insert rather than an update (causing primary key violation)?

I'm trying to use a dataset to update some rows in a database, simple.
I'm creating a typed dataset instance, disabling constraints, adding a few rows to one table and populating a few of the columns in the rows, including the primary key, with existing and correct primary key values. Yet, when I call update on the data adapter it's throwing a primary key violation.
I'm not providing values for every column, only those I want to update. Why does the adapter not recognise an update is required?
MyDataset dataSet = new MyDataset();
dataSet.EnforceConstraints = false;
Simply because you Add() the records... That marks them as new and they will trigger an Insert statement on update.

Categories