Rearrange the autoincrement column value after deleting some rows - c#

The case that a column such as the ID column on a table will auto increment. This simply means that the next insert into the table will have an ID that is one more then the previous one and therefore all ID's will be unique.
However, if you delete a row from the table, the table will auto increment as if the row had not been deleted at all. The result is a gap in the sequence of numbers. This is normally not that much of an issue, but you may want to reset the auto increment field.
PatientNo is primary key and here is the code what I have tried so far
private void txtincr()
{
int a;
if (textPatientNo.Text == "")
{
if (con.State == 0)
{
con.Open();
}
string Query= "select PatientNo from PatientRegistration";
SQLiteDataAdapter DataAdapter = new SQLiteDataAdapter(Query,con);
DataSet PatientDataSet = new DataSet();
DataAdapter.Fill(PatientDataSet);
if (PatientDataSet.Tables[0].Rows.Count != 0)
{
a = PatientDataSet.Tables[0].Rows.Count;
a = a + 1;
textPatientNo.Text = Convert.ToString(a);
textPatientName.Focus();
}
else
{
textPatientNo.Text = "1";
textPatientName.Focus();
}
con.Close();
}
}

When you have declared the column as INTEGER PRIMARY KEY, you don't need to do anything because the database automatically uses the next value after the largest value in the table.
When you have declared the column as INTEGER PRIMARY KEY AUTOINCREMENT, the current counter is stored in the sqlite_sequence table. You can simply modify it by updating that table.

You can try using the SQL Query
DBCC CHECKIDENT('TABLENAME',RESEED,initialvalue);

Related

How to bulk insert data into a table when the primary ID is set with a sequence

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. :/

Cannot insert duplicate key row in object 'dbo.ta_Kullanici' with unique index 'IX_ta_Kullanici'.\r\nThe statement has been terminated

I try to develop a program for insert datas from excel table to SqlServer.
I had an error when I try to insert data to sqlserver. That is my error message here
"Cannot insert duplicate key row in object 'dbo.ta_Kullanici' with
unique index 'IX_ta_Kullanici'.\r\nThe statement has been terminated."
ID is unque and autoincrement In my table.
Thanks for your help! :)
A part of my code is here;
if (!check)
{
kul = new ta_Kullanici();
hata = new KullaniciHata();
hata.AdSoyad = kullanicilar.Rows[i][7].ToString() + " " + kullanicilar.Rows[i][8].ToString();
hatalar.Add(hata);
kul.kul_ad = kullanicilar.Rows[i][7].ToString();
kul.kul_soyad = kullanicilar.Rows[i][8].ToString();
foreach (var bolge in bolgeler)
{
if (kullanicilar.Rows[i][1].ToString().ToLower().IndexOf(bolge.bolge_ad.ToLower()) != -1)
{
kul.kul_bolge_Id = bolge.bolge_Id;
}
}
kul.kul_ikTar = DateTime.Now;
kul.kul_statu = true;
kul.kul_guid = Guid.NewGuid().ToString();
kul.kul_ikIP = "127.0.0.1";
kul.kul_ik_kul_Id = 5;
kul.kul_TCKNo = kullanicilar.Rows[i][9].ToString();
kul.kul_kulAd = kullanicilar.Rows[i][6].ToString();
kul.kul_tip_enm = 2;
if (!string.IsNullOrWhiteSpace(kullanicilar.Rows[i][9].ToString()))
{
kul.kul_sifre = kullanicilar.Rows[i][9].ToString();
}
else
{
kul.kul_sifre = "123123";
}
checkList.Add(kul);
db.ta_Kullanici.Add(kul);
db.SaveChanges();
hatalar.Remove(hata);
}
Have a look at the table in question dbo.ta_Kullanici and see what column the index named IX_ta_Kullanici is on.
The index in question is a unique index, meaning that it will not allow any duplicate values for the column(s)
Remember that this index could be on any column in the table and is not limited to the Primary Key.
So basically the issue is that the column has an index of Unique key and what that index does is that it makes sure duplicate values do not get repeated on the column, to change that what you can do is to go to Management studio, go to the table that has that column, right-click on the column and click to modify. A screen will appear with all the columns displayed. right-click the small box beside the column and select indexes/keys. Then you will see a IsUnique property. set it to 'NO'.

Update the dataset after rows changed

Scenario:
Excel file is read and displayed in datagrid.
Values in sql server must be updated if excel values are different.
Table in Sql server don't have primary key
After all these steps, when I am about to update the table, it throws the error saying "Update requires a valid UpdateCommand when passed DataRow collection with modified rows."
There is no primary key. So I need to use update command. BUt how and what would be in update command? importdata is dictionary where data from excel are stored. PLz help!!! What should I do now? I have No idea....
foreach (DataColumn column in ds.Tables[0].Columns)
{
string fieldName = column.ColumnName;
string fieldNameValueE = string.Empty;
if (importdata.ContainsKey(fieldName))
{
fieldNameValueE = importdata[fieldName];
foreach (DataRow dr in ds.Tables[0].Rows)
{
string fieldNameValueD = dr[fieldName].ToString();
if (fieldNameValueD != fieldNameValueE)
{
dr[fieldName] = fieldNameValueE;
}
}
}
}
da.Update(ds);
connection.Close();
So, let's say we were dealing with a table that had a primary key:
CREATE TABLE TableA
{
FieldA INT PRIMARY KEY IDENTITY(1, 1),
FieldB VARCHAR(256) NULL,
FieldC VARCHAR(256) NOT NULL,
}
If you were to use the SqlCommandBuilder (which you cannot because you don't have a primary key), it would build a statement a bit like this:
UPDATE TableA
SET FieldB = #p1,
FieldC = #p2
WHERE (FieldA = #p3 AND
((FieldB IS NULL AND #p4 IS NULL) OR (FieldB = #p5)) AND
FieldC = #p6)
So, you're going to need to build an UPDATE statement that's very similar to do it the way they do. But one thing you need to remember is it's not just the statement, you also have to add all of the parameters to the command that you build - and that's going to become pretty cumbersome.
So, I have two recommendations for you:
Make a primary key on the table.
Issue an ExecuteNonQuery in every iteration of the loop.
The second recommendation would look like this:
foreach (DataColumn column in ds.Tables[0].Columns)
{
string fieldName = column.ColumnName;
string fieldNameValueE = string.Empty;
if (importdata.ContainsKey(fieldName))
{
fieldNameValueE = importdata[fieldName];
foreach (DataRow dr in ds.Tables[0].Rows)
{
string fieldNameValueD = dr[fieldName].ToString();
if (fieldNameValueD != fieldNameValueE)
{
dr[fieldName] = fieldNameValueE;
}
var cmd = new SqlCommand(string.Format(
"UPDATE importdata SET {0} = {1} WHERE fielda = #fielda AND fieldb = #fieldb ...",
fieldName, fieldNameValueE), connectionObject);
cmd.Parameters.AddWithValue(#fielda, dr["fielda", DataRowVersion.Original]);
cmd.Parameters.AddWithValue(#fieldb, dr["fieldb", DataRowVersion.Original]);
cmd.ExecuteNonQuery();
}
}
}
Use SqlCommandBuilder.
After setting up your DataAdapter, initialize a command builder.
Then use the SqlCommandBuilder update feature.
SqlCommandBuilder cb = new SqlCommandBuilder(da);
//Do your other work updating the data
cb.DataAdapter.Update(ds);
That should do the trick!
Edit:
As BigM pointed out, your table needs to have a primary key for the SqlCommandBuilder to work. If however, you can't modify the actual SQL table and mark one of the fields as a Primary Key and you also know that one of the fields is unique, you can add a Primary Key to your DataSet table like this:
DataColumn[] pk1 = new DataColumn[1];
pk1[0] = ds.Tables["TableName"].Columns[0];
ds.Tables["TableName"].PrimaryKey = pk1;
This gives your "in memory" table a primary key so that the SqlCommandBuilder can do its work.
Warning:
You must be sure that the values in the column you mark as primary key are actually unique.

UNIQUE constraint on DataTable

Can I have a clustered key on DataTable in C# ?
There's a requirement in my code to have constraints for possible combinations of 3 columns to be unique .....
What you need is really a unique constraint on your DataTable. Clustered keys are a SQL Server on-disk feature and not applicable to a DataTable.
Check out MSDN doc on DataTable constraints:
The UniqueConstraint object, which can be assigned either to a single column or to an array of columns in a DataTable, ensures that all data in the specified column or columns is unique per row. You can create a unique constraint for a column or array of columns by using the UniqueConstraint constructor.
So try something like this:
// this is your DataTable
DataTable custTable ;
// create a UniqueConstraint instance and set its columns that should make up
// that uniqueness constraint - in your case, that would be a set of *three*
// columns, obviously! Adapt to your needs!
UniqueConstraint custUnique =
new UniqueConstraint(new DataColumn[] { custTable.Columns["CustomerID"],
custTable.Columns["CompanyName"] });
// add unique constraint to the list of constraints for your DataTable
custTable.Constraints.Add(custUnique);
And that should do the trick for you!
To make your columns enforce a UNIQUE constraint you could use
DataTable dt = new DataTable();
dt.Columns.Add("UniqueColumn");
dt.Columns["UniqueColumn"].Unique = true;
Solution two
If you want some combination of the values in some columns to have unique value, you can try this.
DataTable dt = new DataTable();
dt.Columns.Add("UniqueColumn1");
dt.Columns.Add("UniqueColumn2");
dt.Columns.Add("UniqueColumn3");
dt.Columns.Add("NormalColumn");
string
value1 = string.Empty,
value2 = string.Empty,
value3 = string.Empty,
value4 = string.Empty;
//Logic to take values in string values variables goes here
DataRow[] founded = dt.Select("UniqueColumn1 = '"+ value1+
"' and UniqueColumn2 = '"+value2+
"' and UniqueColumn3 = '"+value3+"'");
if (founded.Length > 0)
// Message to say values already exist.
else
// Add a new row to your dt.
In this code you check the data present in DT to enforce uniqueness

sqlite insert or replace datagridview C#

Regarding the Sqlite insert or replace command.
I am doing the insert if does not exist.
The inserted/updated values come from the datagridview bound to a datatable.
The datatable has a TID column which is the primary key. It also has other columns like Tname,TUtility....
For update statement TID has a value and works well. But for an insert statement I want the serial number(which is the TID column) to be automatically populated.
private void SaveData(DataGridView dgv)
{
using (SQLiteConnection conn = new SQLiteConnection(connString))
{
conn.Open();
dt = dt.GetChanges();
if (dt.Rows.Count > 0)
{
int dtlength = dt.Rows.Count;
DataRow[] arr = new DataRow[dtlength];
dt.Rows.CopyTo(arr, 0);
SQLiteCommand upCmd = new SQLiteCommand(
#"INSERT OR REPLACE
INTO
[Table1](
[TID],
[TName],
[TUtility],
[TType])values(#TID,#Tname,#TUtility,#TType),conn);
for (int i = 0; i < arr.Length; i++)
{
upCmd.Parameters.AddWithValue("#TID", Convert.ToInt32(arr[i]["SNo"]));
upCmd.Parameters.AddWithValue("#TName", arr[i]["Utility"].ToString());
upCmd.Parameters.AddWithValue("#TUtility", arr[i]["Plantname"].ToString());
upCmd.Parameters.AddWithValue("#TType", arr[i]["PlantType"].ToString())
da.UpdateCommand = upCmd;
this.da.UpdateCommand.ExecuteNonQuery();
}
How should I add this TID value in such a way that when the users inserts a new row, it should automatically put the serial number.
I mean: Suppose there are 4rows currently in the DGV. The DGV is in edit mode(*).I am adding a new row. Once the user tries to enter some data in the new row, there should be a serial number already populated.
Thank you
Sun
I am not sure if I understand your problem but why not just put NULL for TID when you do INSERT. Since TID is primary key, the sqlite will insert value automatically.
According to Sqlite FAQ it says this for primary key
whenever you insert a NULL into that column of the table, the NULL is
automatically converted into an integer which is one greater than the
largest value of that column over all other rows in the table, or 1 if
the table is empty.

Categories

Resources