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'
Related
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.
I'm trying to use SqlBulkCopy to insert a number of rows into a table where the Id column is set with a sequence. The sequence and table look something like:
CREATE SEQUENCE [dbo].[MyTableId]
AS [int]
START WITH 1
INCREMENT BY 1
MINVALUE -2147483648
MAXVALUE 2147483647
CACHE 10
GO
CREATE TABLE [dbo].[MyTable](
[Id] [int] NOT NULL,
[SomeColumn] [int] NOT NULL,
[AnotherColumn] [nvarchar](100) NOT NULL
CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
GO
ALTER TABLE [dbo].[MyTable] ADD
CONSTRAINT [DF_MyTable_Id]
DEFAULT (NEXT VALUE FOR [MyTableId]) FOR [Id]
GO
The Code to import the rows looks something like:
var table = new DataTable();
using (var adapter = new SqlDataAdapter($"SELECT TOP 0 * FROM dbo.MyTable", conn))
{
adapter.Fill(table);
}
foreach (Data d in data)
{
var row = table.NewRow();
row["SomeColumn"] = d.someColumnValue;
row["AnotherColumn"] = d.anotherColumnValue;
table.Rows.Add(row);
}
using (var bulk = new SqlBulkCopy(conn))
{
bulk.DestinationTableName = "dbo.MyTable";
bulk.WriteToServer(table);
}
This fails when writing the data to the server because
System.InvalidOperationException: 'Column 'Id' does not allow DBNull.Value.'
I have tried removing the Id column from the table definition, but this just puts the column ordinals off by one. I've tried setting the Id row to:
table.Columns["Id"].AutoIncrement = true;
but this ignores the sequence, and on repeated runs of the import, restarts the auto-increment value from 0.
How would I instruct the server to generate a new Id value using its sequence? Or is it possible to separately generate a number of values for the sequence prior to creating the new rows in the table?
What about asking SQL Server for the current sequence value, through a SqlCommand.ExecuteScalar(). Use this SQL statement as the input for the command:
SELECT current_value
FROM sys.sequences
WHERE OBJECT_ID = OBJECT_ID(N'dbo.MyTableId');
Then set column property AutoIncrementSeed to the previous value plus one:
// ... code to get current sequence value
string sqlText = <above sql goes here>;
SqlCommand getSeqValue = new(sqlText, your_connection);
long currentSequenceValue = (long)getSeqValue.ExecuteScalar();
// Construct DataTable structure
// maybe replacing adapter.Fill(table);
// with
//adapter.FillSchema(table,SchemaType.Source);
// tell table to start ID on current sequence value + 1 (or AutoIncrementStep)
table.Columns["Id"].AutoIncrement = true;
table.Columns["Id"].AutoIncrementSeed = currentSequenceValue + 1;
// prepare things and bulk insert
Just an idea, haven't tested. :/
I'm working with TSQL and C#. I have two queries that return strings:
string[] allSubcategories = dt.AsEnumerable().Select(x => x.Field<string>("SubcategoryName")).Distinct().ToArray();
var redMark = db.GetTableBySQL("SELECT * FROM RedMarkItems");
string[] redMarkColumns = redMark.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToArray();
So, as you can see I have two different arrays, first I get subcategoriesNames:
and all columns of table RedMarkItems:
That I want to do is to create column dynamically, I mean, if subcategorieName does not exist as column in RedMarkItems do an Update and create it someting like:
var createColumn = db.ExeSQL($"ALTER TABLE RedMarkItems ADD {ColumnName} BIT");
How can I compare if subcategorieName does not exist as column in RedMarkItems table? Then create column as my query? Regards
If you want to know if a particular column exists in an already filled DataTable using the Linq approach then it is just:
bool exists = redMark.Columns.Cast<DataColumn>().Any(x => x.ColumnName == "SubCategoryName");
Instead, if you want to ask this info directly to the database then use the INFORMATION_SCHEMA views The Columns view is the one to use with a query like this.
string query = #"IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.Column
WHERE Column_Name = #colName)
SELECT 1 ELSE SELECT 0";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Parameters.Add("#colName", SqlDbType.NVarChar).Value = "SubCategoryName";
bool exists = (cmd.ExecuteScalar() == 1);
Now, the part about creating the column is pretty simple as code per se. It is just an appropriate ALTER TABLE. But there are a lot of things to be cleared before. What will be the datatype of the new column? What will be its length and precision? What will be the constraints applied to it (Null/Not Null defaults etc)? As you can see all these info are very important and require to be defined somewhere in your code.
var sdr = db.ExecuteReader("SELECT [key],translation FROM language WHERE lang=#lang");
DataTable someTable = new DataTable();
someTable.Load(sdr);
return ((string)(someTable.Rows.Find("[key] = CUSTOMDATEFORMAT").ItemArray[1]));
The last line now throws the error System.Data.MissingPrimaryKeyException: "The table has no primary key."
So I guess it finds the keyword "key" and now expects me to query on the primary key column, not the column named "key". How do I have to escape the column name?
If you want to use DataRowCollection.Find you have to specify the DataTable's PrimaryKey(s).
I would use Linq-To-DataTable:
DataRow row = someTable.AsEnumerable()
.FirstOrDefault(row => row.Field<string>("key") == "CUSTOMDATEFORMAT");
if(row != null)
return row.Field<string>(1); // or by name but with correct type
else
return "something else";
Then you can use all methods you want in the query.
The Find method is used to find a single rows by the primary key value. Use Select to find rows by arbitrary column values:
DataRow[] foundRows;
foundRows = someTable.Select("[key] = CUSTOMDATEFORMAT");
return foundRows[0].ItemArray[1]; // adding proper bounds checking, of course.
Find method is using the column that is specified in the DataTable object as primary key and return a row that contains the value it gets inside the primary key cell.
From MSDN:
Gets the row specified by the primary key value.
Since your table doesn't have a column that is specified as a primary key, you get this error.
If your key column is guaranteed to not contain duplicates, you can specify it as the primary key using the DataTable's PrimaryKey property.
If not, then use Linq's Select method instead of find:
return ((string)(someTable.Rows.Select("[key] = CUSTOMDATEFORMAT").ItemArray[1]));
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.