Update a set of rows of a table having no primary key - c#

I want to update set of rows using ODP.net.
I want to get list of employees based on increasing asscending order of PRIORITY and update PRIORITY column with value 1 and increment by 1.
I tried below approach and it gives error "Dynamic SQL generation failed. No key information found"
StrQuery = "SELECT * FROM EMPLOYEE WHERE DEPT ='" + dept + "' ORDER BY PRIORITY";
DataTable dt = new DataTable();
OracleDataAdapter da = new OracleDataAdapter();
da.SelectCommand = new OracleCommand(StrQuery, ora);
OracleCommandBuilder cb = new OracleCommandBuilder(da);
da.Fill(dt);
intNpriority = 1;
foreach (DataRow row in dt.Rows)
{
row["PRIORITY"] = intNpriority;
intNpriority = intNpriority + 1;
}
da.UpdateCommand = cb.GetUpdateCommand();
da.Update(dt);
The table has no primary key and i cannot add one now. Can i add custom update query and how? Is there anyalternative way to acheive same?
table strucure:
column name | (data type)
Employee_name | (varchar2)
dept | (varchar2)
PRIORITY | (NUMBER)

I've spent two days to find some way to workaround.
Lucky that I could get it done.
The idea is to add a dump primary key in the DataTable, this new dump column does not affect the real database table.
Here's my code sample
Dim currentRow = m_DataTable.Rows(m_RowPosition)
Dim tmpRows() As DataRow = {currentRow}
Dim cmdBuilder As OracleCommandBuilder = New OracleCommandBuilder(m_Adapter)
**If m_DataTable.PrimaryKey.Count = 0 Then
m_DataTable.Columns.Add(New DataColumn("_ID_", System.Type.GetType("System.String")))
m_DataTable.Columns("_ID_").Unique = True
End If**
m_Adapter.Update(tmpRows)
Note: The currentRow is the row is being edited .
Please consider carefully to apply this tip because it might update all data of table.
It's suitable for case your table has only one row ( some kind of configuration data )

Related

How to sort DataSet by column [duplicate]

This question already has answers here:
Sorting a Data Table
(5 answers)
Closed 4 years ago.
My SQL database was created in SQL Server Management Studio. I have a dataset table that works great, which was sorted by the primary key id column from an example I copied, which was fine when there were only a few entries. Now I want to sort by the Model_no column.
I have tried to sort the table like this:
ds.Tables[0].DefaultView.Sort = "Model_no";
and like this:
DataTable table = ds.Tables[0];
DataView view = table.DefaultView;
view.Sort = "Model_no";
But the table is still sorted by primaryKey.
objConnect = new DatabaseConnection();
conString = "Server=VENUS;" +
"Initial Catalog=TestRig;" +
"User id=TestRig;" +
"Password=act1ve;" +
"MultipleActiveResultSets = true;";
objConnect.connection_string = conString;
objConnect.Sql = Properties.Settings.Default.SQL;
ds = objConnect.GetConnection;
DataTable table = ds.Tables[0]; // Neither this
DataView view = table.DefaultView;
view.Sort = "Model_no";
// ds.Tables[0].DefaultView.Sort = "Model_no"; // or this work
// When I click next record, I inc the row, then get the datarow and
display in my form
inc++;
dRow = ds.Tables[0].Rows[inc];
dummy = dRow.ItemArray.GetValue(0).ToString(); // Primary Id
exVol = dRow.ItemArray.GetValue(1).ToString();
tbExcitationVoltage.Text = exVol.Trim();
When I open the form I expect the first entry to be sorted by the model number, but instead see record 1 (primary ID), how can I sort by another column please?
You need to read from DefaultView. If you need to read from the table you can do the following.
ds.Tables[0].DefaultView.Sort = "Model_no";
DataTable dt = ds.Tables[0].DefaultView.ToTable();

Checking a value from DB to see if it's a boolean and setting combobox as such throws exception

I have a small project I've been working on. What I'm doing is - I add a value in the database, the table looks as such...
ProductID, ProductName, Status
1 Gold 0
Status is a Bit(1)
Since I only have two values in the drop down for Status, I use the combobox.selectedIndex - to capture the value of the field - either 0 or 1.
Once I insert the values into the table, I try to populate a datagrid with everything saved in this particular table in DB...
Here's what I'm doing...
MySqlDataAdapter sda = new MySqlDataAdapter("SELECT * from PRODUCTS ", con);
DataTable dt = new DataTable();
sda.Fill(dt);
dataGridView1.Rows.Clear();
foreach (DataRow item in dt.Rows)
{
int n = dataGridView1.Rows.Add();
dataGridView1.Rows[n].Cells[0].Value = item["ProductCode"].ToString();
dataGridView1.Rows[n].Cells[1].Value = item["ProductName"].ToString();
if ((bool)item["Status"]) // Trying to capture the value from DB and set the combobox with the correct .Value
{
dataGridView1.Rows[n].Cells[2].Value = "Active";
}
else
{
dataGridView1.Rows[n].Cells[2].Value = "Deactive";
}
The exception I get comes from this line of code..
if ((bool)item["ProductStatus"])
System.InvalidCastException: 'Specified cast is not valid.'
It looks like this is a popular error and trying to google gives me a hundred different scenarios. ANyone have any idea what I'm doing wrong?
If it's a bit column as you say in your post then there shouldn't be any issue at all but mostly it's not. Moreover, you are going round instead going straight ... I mean change your query like below and directly bind to your grid
SELECT productId, productName,
case when Status = 1 then 'Active' else 'Deactive' end as Status
FROM PRODUCTS
Bind it to the gridview
ySqlDataAdapter sda = new MySqlDataAdapter("query here ", con);
DataTable dt = new DataTable();
sda.Fill(dt);
dataGridView1.Rows.Clear();
dataGridView1.DataSource = dt; //bind the data

C# How create primary key to existing table column

I would like to ask for your help. The problem is that I am trying to relate two tables so I need to create primary keys on the tables each "id" columns but I am getting an error on this line
ds.Relations.Add(dr);
Error:
This constraint cannot be enabled as not all values have corresponding parent values.
(original error in Spanish = No se puede habilitar esta restricción ya que todos los valores no tienen los valores primarios correspondientes.)
What am I doing wrong?
OdbcDataAdapter sdata = new OdbcDataAdapter("SELECT * FROM componentes WHERE nombre_componente ILIKE '%" + buscar + "%'", conn);
OdbcDataAdapter sdata2 = new OdbcDataAdapter("SELECT * FROM proveedores WHERE nombre_empresa ILIKE '%" + buscar + "%'", conn);
DataSet ds = new DataSet();
DataTable dtbl = new DataTable("dtbl");
DataTable dtbl2 = new DataTable("dtbl2");
sdata.Fill(dtbl);
sdata2.Fill(dtbl2);
ds.Tables.Add(dtbl);
ds.Tables.Add(dtbl2);
dtbl.PrimaryKey = new DataColumn[] { dtbl.Columns["id"] };
dtbl2.PrimaryKey = new DataColumn[] { dtbl2.Columns["id"] };
DataRelation dr = new DataRelation("provcomp",
ds.Tables["dtbl"].Columns["id_prov_comp"],
ds.Tables["dtbl2"].Columns["id"]);
ds.Relations.Add(dr);
ds.AcceptChanges();
Thanks in advance.
The primary keys are ok - you already successfully created them with the following lines:
dtbl.PrimaryKey = new DataColumn[] { dtbl.Columns["id"] };
dtbl2.PrimaryKey = new DataColumn[] { dtbl2.Columns["id"] };
The problem is (as indicated by the exception) in the DataRelation. DataRelation is the equivalent of the database FK (foreign key). The signature of the used constructor looks like this:
public DataRelation(
string relationName,
DataColumn parentColumn,
DataColumn childColumn
)
I think what you did wrong is specifying the wrong columns - parentColumn should point to the table being referenced while childColumn - the table referencing it.
Simple change it to:
DataRelation dr = new DataRelation("provcomp",
ds.Tables["dtbl2"].Columns["id"],
ds.Tables["dtbl"].Columns["id_prov_comp"]);
and if they are really related correctly, the problem should be solved.
Edit: In case the parent table does not contain all the keys from the child table, you might consider using this constructor overload and pass createConstraints = false, which will prevent the exception, but note that some child records will not to find their parent record.
DataRelation dr = new DataRelation("provcomp",
ds.Tables["dtbl2"].Columns["id"],
ds.Tables["dtbl"].Columns["id_prov_comp"],
false);
The problem here is your data. You're adding a primary key to each table and then attempting to link them with a foreign key.
However, from the error message you are receiving, it sounds like you are attempting to link dtbl to an id from dtbl2 which does not exist.
I would try to do a SQL query to find out where your problem records lie and then choose to either add a "parent", change the parent or delete the record.
SELECT * FROM componentes WHERE id_prov_comp NOT IN (SELECT ID FROM proveedores )
The parent column (that is primary key) must come before the child column (that is foreign key). Try this:
DataRelation dr = new DataRelation("provcomp",
ds.Tables["dtbl2"].Columns["id"],
ds.Tables["dtbl"].Columns["id_prov_comp"]);

DataAdapter Update not properly Inserting data into SQL Server?

I have 2 DataTables: 1 that is filled with all the data from a table in my database called Ticket_Report, and a second one that is filled with new tickets.
I am searching the Ticket_report datatable for duplicates from the new ticket DataTable (and deleting them). Then I merge the new tickets datatable into the Ticket_report datatable.
I then try and Update the Ticket_Report table in SQL Server with the newly edited Ticket_report datatable. I am expecting the Update method to Update the table in SQL Server with rows that have matching primary keys from the datatable, and Insert rows that don't exist.
I am not getting any errors, however it doesn't seem like the rows are being updated/inserted.
con.Open();
DataTable ticketReportDT = new DataTable();
ticketReportDT = newTicketdt.Clone();
ticketReportDT.Columns[0].Unique = true;
SqlCommand cmd2 = new SqlCommand("SELECT * FROM ticket_report", con);
SqlDataAdapter da = new SqlDataAdapter(cmd2);
da.Fill(ticketReportDT);
da.UpdateCommand = new SqlCommandBuilder(da).GetUpdateCommand();
int currentTicketCount = ticketReportDT.Rows.Count;//3234
int newTicketCount = newTicketdt.Rows.Count; //339
//Removing Duplicate tickets in ticketReportDt
foreach (DataRow NewTicketsRow in newTicketdt.Rows)
{
foreach (DataRow currentTicketsRow in ticketReportDT.Select())
{
if (currentTicketsRow.Field<string>(ticketReportDT.Columns[0]) == NewTicketsRow.Field<string>(newTicketdt.Columns[0]))
{
currentTicketsRow.Delete();
}
}
}
ticketReportDT.AcceptChanges();
int currentTicketCount2 = ticketReportDT.Rows.Count;//2903, is less than last count because duplicates removed
ticketReportDT.Merge(newTicketdt);//add new tickets to ticketReportDT
ticketReportDT.AcceptChanges();
int currentTicketCount3 = ticketReportDT.Rows.Count;//3242, count went up because new tickets added
da.Update(ticketReportDT);//apply changes to database table Ticket_Report
con.Close();
Console.WriteLine("Ticket Transfer Complete");
This runs without error. To test, I did a count query in SQL Server before and after this update.
Before update:
select count(*) from TICKET_REPORT
// = 3234
After Update:
select count(*) from TICKET_REPORT
// = 3234 <-Should be 3242 (row count of ticketReportDT)
It seems like the Datatable has the correct amount of rows, but when I do the update, this does not reflect in SQL Server. Am I doing something wrong?
Since you have called ticketReportDT.AcceptChanges() before updating database it is not going to update anything in the database.

DBConcurrency Exception Occured While Updating Using Dataadapter

I am trying to edit DataTable Filled by NpgsqlDataAdapter.
After calling Fill() method, I have only one row in DataTable. Then I changed value of one column only and tried to update as below.
Then I am getting this error:
DBConcurrencyException occured
My code is:
NpgsqlDataAdapter getAllData = new NpgsqlDataAdapter("SELECT sn,
code,product, unitprice, quantity, InvoiceNo, Date FROM stocktable WHERE Code='" + product + "'
ORDER BY EDate ASC", DatabaseConnectionpg);
DataTable ds1 = new DataTable();
ds1.Clear();
getAllData.Fill(ds1);
if (ds1.Rows.Count > 0)
{
ds1.Rows[0]["Quantity"] = qty;// calculated value
}
ds1 = ds1.GetChanges();
NpgsqlCommandBuilder cb = new NpgsqlCommandBuilder(getAllData);
//getAllData.RowUpdating += (sender2, e2) => { e2.Command.Parameters.Clear(); };
//cb.SetAllValues = false;
getAllData.DeleteCommand = cb.GetDeleteCommand();
getAllData.InsertCommand = cb.GetInsertCommand();
getAllData.UpdateCommand = cb.GetUpdateCommand();
int x = getAllData.Update(ds1);
if (x > 0)
{
ds1.AcceptChanges();
}
EDIT: I have three fields as primary keys and I am calling only two fields in select statement. Is it reason for DBConcurrency error? But I am able to update the table with same (three fields as primary key) parameters in SQL Server 2005.
UPDATE:
I found the solution and the solution is
I created and used second DataAdapter to update data.
I used getAllData(NpgSqlDataAdapter) To fill table as
NpgsqlDataAdapter getAllData = new NpgsqlDataAdapter("SELECT
code,product, unitprice, quantity, InvoiceNo, Date FROM stocktable WHERE Code='" + product + "'
ORDER BY EDate ASC", DatabaseConnectionpg);
And Also created next Adapter to update as
NpgsqlDataAdapter updateadap= new NpgsqlDataAdapter("SELECT sn, quantity FROM stocktable WHERE Code='" + product + "'
ORDER BY EDate ASC", DatabaseConnectionpg);
NpgsqlCommandBuilder cb = new NpgsqlCommandBuilder(updateadap);
//getAllData.RowUpdating += (sender2, e2) => { e2.Command.Parameters.Clear(); };
//cb.SetAllValues = false;
updateadap.DeleteCommand = cb.GetDeleteCommand();
updateadap.InsertCommand = cb.GetInsertCommand();
updateadap.UpdateCommand = cb.GetUpdateCommand();
int x = updateadap.Update(ds1);
if (x > 0)
{
......
}
I tried alot and found that NpgsqlDataAdapter had problem with Column Code. When i ommited it then it worked. DataType of column code is varchar. I don't know why this was happening. Anybody has idea about it?
This is because DataAdapter uses Optimistic Concurrency by default. This means that if you are trying to update a row that no longer exists in the database or changed, the update from the DataAdapter will fail with the exception above.
Possible scenarios:
Between you selecting the data into the client and sending the
update, another user is deleting or updating this row from his application.
It can be that you are deleting the data from somewhere else in your application.
For example:
You fill the DataTable that will be used for the update.
Deletes the row with Code = 1101 (for example) directly from the database, i.e. you do not use the DataTable here. This is emulating another user deleting the row with Code = 1101 from another application. Or some other part in your code deleting the row with Code = 1101.
Selects out the row with Code = 1101 from the DataTable, this is just to show that it is still there even though you have deleted it from the database itself.
Edits the Quantity column in the row with Code = 1101 in the DataTable. This has to be done, otherwise the call to Update will ignore this row when updating.
Executes the update, this will throw the exception since you are trying to update a row that (no longer) exists in the database.
If you want to implement Last Writer Wins, Add the following code:
cb.ConflictOption = ConflictOption.OverwriteChanges;
Also there is one more possible thing : if you have Decimal/numeric as columns in the DB they may cause this error even though the data looks the same. This is due to a decimal rounding error.
An important note:
You should always use parameterized queries by the way. This kind of string concatenations are open for SQL Injection.

Categories

Resources