I read upon a document on how to retrieve the last record after inserted. However when I do, nothing gets filled on the datagridview. This is what I have.
static String connectionString = #"Data Source = (LocalDB)\MSSQLLocalDB;AttachDbFilename= C:\Users\home\Documents\C# Programs\program\Database.mdf ;Integrated Security = True";
private void displayLastInsertedRecord()
{
using (SqlDataAdapter dataAdapter = new SqlDataAdapter("select ##identity", connectionString))
{
DataTable table = new DataTable(connectionString);
dataAdapter.Fill(table);
employeeDataGridView.DataSource = table;
}
}
I checked to see if in fact the data is being stored into the database table and it actually is. It just not display factors such as their name, city, address, etc etc.Cannot figure out what I am doing incorrectly.
Your query is returning a single row, single column table, which contains the Primary Key value of the last inserted data row, in any table in your database, provided that such primary key is an IDENTITY column. Since you want the actual data, change your query from:
SELECT ##IDENTITY
to:
SELECT #LastID = ##IDENTITY; SELECT * FROM [YourTableName] WHERE [YourPrimaryKeyColumn] = #LastID
where [YourTableName] is the table you're interested in getting the inserted row from (must match last insert command, otherwise the returned dataset will either contain no rows, or have an accidentally matching record - basically, garbage data), and [YourPrimaryKeyColumn] is the name of the primary key column in the aforementioned table.
Also, consider using SCOPE_IDENTITY or IDENT_CURRENT instead.
Related
I did a search and found some seemingly related answers, but they don't really do what I'm after.
Given a valid connection string and a table name, I want to get a DataTable of the table. I.e. if the table has a column called "Name", I want the DataTable set up so I can do dt["Name"] = "blah";
The trick is, I don't want to hard code any of that stuff, I want to do it dynamically.
People tell you to use SqlConnection.GetSchema, but that gives you back a table with a bunch of stuff in it.
Everybody has random tricks like TOP 0 * from the table and get the schema from there, etc.
But is there a way to get the table with the primary keys, unique indexes, etc. Ie.. in the final format to do a bulk insert.
You can use SqlDataAdapter.FillSchema:
var connection = #"Your connection string";
var command = "SELECT * FROM Table1";
var dataAdapter = new System.Data.SqlClient.SqlDataAdapter(command, connection);
var dataTable = new DataTable();
dataAdapter.FillSchema(dataTable, SchemaType.Mapped);
This way you will have an empty DataTable with columns and keys defined and ready to use in code like dataTable["Name"] = "blah";.
I have a DataTable with new entries, and I want to add these to an existing database.
So I create a SqlDataAdapter and fill a second table with it, then I merge the two tables, and update the database, but nothing happens, the return value is 0, the database stays the same.
Here's my code:
DBManager.DBDestinationConnect(textBox10.Text, textBox9.Text, textBox8.Text, textBox7.Text, ref destinationConnection);
//DBManager is a Class, to connect with the database
CategoryAdapterBackup = new SqlDataAdapter("SELECT*FROM " + tablename, destinationConnection);
CategoryTableBackup = new DataTable();
CategoryAdapterBackup.Fill(CategoryTableBackup);
CategoryTableBackup.Merge(SubTable);
//SubTable is the DataTable with the new entries
CategoryAdapterBackup.Update(CategoryTableBackup);
I'm having a problem discerning your intentions with this code. Why not simply use sqlbulkcopy on SubTable? That would append the contents of SubTable to the destination SQL table. If you are afraid of duplicates, then insert the contents of SubTable Table to a Temp in the DB and maybe use a Join to insert rows into the destination table where not exists row in destination table.
Try with CategoryAdapterBackup.Flush() or with DBManager.Flush()
also, could be a good idea replace SELECT*FROM by SELECT * FROM (with spaces)
I created a table in a database with identity column called id . when i delete data from this table and add new data the id column is still increased by 1 , i need to make this column start increasing from the last id inside this table not the deleted one what should i do ?
this is the datagridview with some records:
this is the delete code
if (comboBoxdelete.SelectedIndex != -1)
{
SqlConnection con = new SqlConnection();
SqlCommand cmd = new SqlCommand();
con.ConnectionString = "Data Source=MOHAMEDSAFWAT;Initial Catalog=Card;Integrated Security=True";
cmd.CommandText = "DELETE FROM [Employee] WHERE [int]=#id1";
cmd.Connection = con;
cmd.Parameters.AddWithValue("#id1", comboBoxdelete.SelectedItem);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
load();
View();
}
else
{
MessageBox.Show(" Please Insert ID First");
}
Identity column (in SQL-Sever) is handled by by RDBMS. It will be increased any time you add some row to the table, when removing rows the RDBMS will not rollback the underlying sequence of the identity column.
Id or primary key of your tables are for internal usage of your application. normaly you must not show them to the user.
do not use the id column as row number for end user (as any thing is showing to the user will be compromizer to be requested to be updated or deleted)
By the way lets think we need to implement the id column manually to full fill your requiment.
We can use a simple approach: When adding any new row first we call a select to fetch the new id:
SELECT ISNULL(count(*),0)+ 1 as newid from Employee
We will have the new id.
know the delete scenario, think that we have
Employee1-->id = 1
Employee2-->id = 2
Employee3-->id = 3
Employee4-->id = 4
Now we delete Employee2 so what is needed to be done?
We need updates(after detecting rows to be updated) like this, to achieve your requirement:
Update Employee3 set id = 2
Update Employee4 set id = 3
For all rows in the table!
It will not work in large amount of data, id is the primary key when updating, all child records must also be updated, re-indexing, table locking and ... will be inevitable.
All this is because the id column is being showed to the user and you need that to be shown sequentially.
Use another non key column like Employee-Number or a UI level column like RowNumber for these scenario and do not show your primary key to the user.
I have come across a problem in using the DataAdapter, which I hope someone can help with. Basically I am creating a system, which is as follows:
Data is read in from a data source (MS-Access, SQL Server or Excel), converted to data tables and inserted into a local SQL Server database, using DataAdapters. This bit works fine. The SQL server table has a PK, which is an identity field with auto increment set to on.
Subsequent data loads read in the data from the source and compare it to what we already have. If the record is missing then it is added (this works fine). If the record is different then it needs to be updated (this doesn't work).
When doing the differential data load I create a data table which reads in the schema from the destination table (SQL server) and ensures it has the same columns etc.
The PK in the destination table is column 0, so when a record is inserted all of the values from column 1 onwards are set (as mentioned this works perfectly.). I don't change the row status for items I am adding. The PK in the data table is set correctly and I can confirm this.
When updating data I set column 0 (the PK column) to be the value of the record I am updating and set all of the columns to be the same as the source data.
For updated records I call AcceptChanges and SetModified on the row to ensure (I thought) that the application calls the correct method.
The DataAdapter is set with SelectCommand and UpdateCommand using the command builder.
When I run, I have traced it using SQL profiler and can see that the insert command is being ran correctly, but the update command isn't being ran at all, which is the crux of the problem. For reference an insert table will look something like the following
PK Value1 Value 2 Row State
== ====== ======= =========
124 Test1 Test 2 Added
123 Test3 Test4 Updated
Couple of things to be aware of....
I have tested this by loading the row to be changed into the datatable, changing some column fields and running update and this works. However, this is impractical for my solution because the data is HUGE >1Gb so I can't simply load it into a datatable without taking a huge performance hit. What I am doing is creating the data table with a max of 500 rows and the running the Update. Testing during the initial data load showed this to be the most efficient in terms of memory useage and performance. The data table is cleared after each batch is ran.
Anyone any ideas on where I am going wrong here?
Thanks in advance
Andrew
==========Update==============
Following is the code to create the insert/update rows
private static void AddNewRecordToDataTable(DbDataReader pReader, ref DataTable pUpdateDataTable)
{
// create a new row in the table
DataRow pUpdateRow = pUpdateDataTable.NewRow();
// loop through each item in the data reader - setting all the columns apart from the PK
for (int addCount = 0; addCount < pReader.FieldCount; addCount++)
{
pUpdateRow[addCount + 1] = pReader[addCount];
}
// add the row to the update table
pUpdateDataTable.Rows.Add(pUpdateRow);
}
private static void AddUpdateRecordToDataTable(DbDataReader pReader, int pKeyValue,
ref DataTable pUpdateDataTable)
{
DataRow pUpdateRow = pUpdateDataTable.NewRow();
// set the first column (PK) to the value passed in
pUpdateRow[0] = pKeyValue;
// loop for each row apart from the PK row
for (int addCount = 0; addCount < pReader.FieldCount; addCount++)
{
pUpdateRow[addCount + 1] = pReader[addCount];
}
// add the row to the table and then update it
pUpdateDataTable.Rows.Add(pUpdateRow);
pUpdateRow.AcceptChanges();
pUpdateRow.SetModified();
}
The following code is used to actually do the update:
updateAdapter.Fill(UpdateTable);
updateAdapter.Update(UpdateTable);
UpdateTable.AcceptChanges();
The following is used to create the data table to ensure it has the same fields/data types as the source data
private static DataTable CreateDataTable(DbDataReader pReader)
{
DataTable schemaTable = pReader.GetSchemaTable();
DataTable resultTable = new DataTable(<tableName>); // edited out personal info
// loop for each row in the schema table
try
{
foreach (DataRow dataRow in schemaTable.Rows)
{
// create a new DataColumn object and set values depending
// on the current DataRows values
DataColumn dataColumn = new DataColumn();
dataColumn.ColumnName = dataRow["ColumnName"].ToString();
dataColumn.DataType = Type.GetType(dataRow["DataType"].ToString());
dataColumn.ReadOnly = (bool)dataRow["IsReadOnly"];
dataColumn.AutoIncrement = (bool)dataRow["IsAutoIncrement"];
dataColumn.Unique = (bool)dataRow["IsUnique"];
resultTable.Columns.Add(dataColumn);
}
}
catch (Exception ex)
{
message = "Unable to create data table " + ex.Message;
throw new Exception(message, ex);
}
return resultTable;
}
In case anyone is interested I did manage to get around the problem, but never managed to get the data adapter to work. Basically what I did was as follows:
Create a list of objects with an index and a list of field values as members
Read in the rows that have changed and store the values from the source data (i.e. the values that will overwrite the current ones in the object). In addition I create a comma separated list of the indexes
When I am finished I use the comma separated list in a sql IN statement to return the rows and load them into my data adapter
For each one I run a LINQ query against the index and extract the new values, updating the data set. This sets the row status to modified
I then run the update and the rows are updated correctly.
This isn't the quickest or neatest solution, but it does work and allows me to run the changes in batches.
Thanks
Andrew
I have a gridview 'GridViewMcm" with dropdownlists while editing in first and second columns and textboxes in next two columns. PairId is the Primary Key of the table.
Following is the code for Onrowupdating event.
SqlConnection mySQLconnection = new SqlConnection(con);
mySQLconnection.Open();
DropDownList drdList1, drdlist2;
drdList1 = (DropDownList)(GridViewMcm.Rows[e.RowIndex].Cells[0].FindControl("ddeditfrom"));
drdlist2 = (DropDownList)(GridViewMcm.Rows[e.RowIndex].Cells[1].FindControl("ddeditto"));
TextBox txtrate, txtdesc;
txtrate = (TextBox)(GridViewMcm.Rows[e.RowIndex].Cells[2].FindControl("txteditrate"));
txtdesc = (TextBox)(GridViewMcm.Rows[e.RowIndex].Cells[3].FindControl("txteditdesc"));
SqlCommand strupdate = new SqlCommand("Update mcmtable set Measure1FromSymbol = #Measure1FromSymbol, Measure2ToSymbol = #Measure2ToSymbol, ConversionRate = #ConversionRate, ConversionDesc = #ConversionDesc Where MeasurePairId=#PairId", mySQLconnection);
strupdate.Parameters.Add("#Measure1FromSymbol", SqlDbType.Text).Value = drdList1.SelectedValue;
strupdate.Parameters.Add("#Measure2ToSymbol", SqlDbType.Text).Value = drdlist2.SelectedValue;
strupdate.Parameters.Add("#ConversionRate", SqlDbType.Decimal).Value = decimal.Parse(txtrate.Text);
strupdate.Parameters.Add("#ConversionDesc", SqlDbType.Text).Value = txtdesc.Text;
strupdate.Parameters.Add("#PairId", SqlDbType.Int).Value = Convert.ToInt32(GridViewMcm.DataKeys[e.RowIndex].Values[0].ToString());
strupdate.ExecuteNonQuery();
GridViewMcm.EditIndex = -1;
Here is the error which am getting while executing the above code:
"Violation of UNIQUE KEY constraint
'U_mcmtable''. Cannot insert duplicate
key in object 'mcmtable'. The
statement has been terminated."
I found the problem to be that the dropdownlist values 'drdlist1.SelectedValue' and 'drdlist2.SelectedValue' are not able to fetch the selectedvalue in the dropdownlist but fetching some default value. And as the default values which they are fetching are already present in the table as a combination in a particular row, it is throwing the error. Is there any mistake in the code part above??
Check the U_mcmtable constraint in the database. My guess is that the constraint is set for the from and to fields and that you're trying to update to a conversion combination that's already in the table.
Check the data that you are attempting to insert/update in the affected table(s). Verify that the data you are attempting to insert/update does not already exist in the table that could cause the UNIQUE KEY constraint to fail.
That Error Denotes That you are trying To insert duplicate value in the column name [Name]
A Unique Constraint Has Been Set on that column Which means The values In that column
Should Be unique
You can get the list of all constraints on your mcmtable table by
SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
where Table_Name='mcmtable'