Sql Server CE - Temporary disable auto increment on a specific column - c#

I have this little question that's been on my mind for a while now.
Here it goes:
Is it possible to temporary disable the Auto_Increment on the column ID.
So that I can add a new row to the table and being able specify the ID value when inserting the row.
And then in the end enable the Auto_Increment again, and let do its work as usual?
And if its possible how can I do it?
The table structure is very simple
Column name (attributes)
ID (Primary Key, Auto Increment, int, not null)
Name (nvarchar(100), not null)
Note:
The table name is: People.
Let's also consider that the table already has data and cannot be changed.
The database server is SQL Server CE.
The SQL commands will be executed in a C# program, if it's of any help.
I really hope its possible, it would come very handy.
Thanks
EDIT
SqlActions SqlActions = new SqlActions();
SqlCeCommand SqlCmd = new SqlCeCommand("SET IDENTITY_INSERT People ON", SqlActions.Connection());
try
{
SqlCmd.ExecuteNonQuery();
}
catch (SqlCeException Error)
{
Console.WriteLine(Error.ToString());
}
string query = "INSERT INTO People SET (ID, Nome) VALUES (#ID, #Nome)";
SqlCeCommand SqlInsert = new SqlCeCommand(query, SqlActions.Connection());
SqlInsert.Parameters.AddWithValue("#ID", 15);
SqlInsert.Parameters.AddWithValue("#Nome", "Maria");
try
{
SqlInsert.ExecuteNonQuery();
}
catch (SqlCeException Error)
{
Console.WriteLine(Error.ToString());
}
The connection string is working, I have tried it.
He reports:
There was an error parsing the query.
[ Token line number = 1,Token line
offset
= 20,Token in error = SET ]
SOLUTION thanks to OrbMan
SqlActions SqlActions = new SqlActions();
SqlCeCommand SqlCmd = new SqlCeCommand("SET IDENTITY_INSERT People ON", SqlActions.Connection());
try
{
SqlCmd.ExecuteNonQuery();
string query = "INSERT INTO People (ID, Nome) VALUES (#ID, #Nome)";
SqlCmd.CommandText = query;
SqlCmd.Parameters.AddWithValue("#ID", 15);
SqlCmd.Parameters.AddWithValue("#Nome", "Vania");
SqlCmd.ExecuteNonQuery();
}
catch (SqlCeException Error)
{
Console.WriteLine(Error.ToString());
}

I believe you can use SET IDENTITY_INSERT. I am not sure if this works in all versions.
Update 2:
Try this version:
SqlActions SqlActions = new SqlActions();
SqlCeCommand SqlCmd = new SqlCeCommand("SET IDENTITY_INSERT People ON", SqlActions.Connection());
try
{
SqlCmd.ExecuteNonQuery();
string query = "INSERT INTO People (ID, Nome) VALUES (#ID, #Nome)";
SqlCmd.CommandText = query;
SqlCmd.Parameters.AddWithValue("#ID", 15);
SqlCmd.Parameters.AddWithValue("#Nome", "Maria");
SqlCmd.ExecuteNonQuery();
}
catch (SqlCeException Error)
{
Console.WriteLine(Error.ToString());
}

Related

How do I assign an out parameter from SQL into a C# variable? [duplicate]

I am having a problem returning an output parameter from a Sql Server stored procedure into a C# variable. I have read the other posts concerning this, not only here but on other sites, and I cannot get it to work. Here is what I currently have. Currently I am just trying to print the value that comes back. The following code returns a null value. What I an trying to return is the primary key. I have tried using ##IDENTITY and SCOPE_INDENTITY() (i.e. SET #NewId = SCOPE_IDENTITY()).
Stored Procedure:
CREATE PROCEDURE usp_InsertContract
#ContractNumber varchar(7),
#NewId int OUTPUT
AS
BEGIN
INSERT into [dbo].[Contracts] (ContractNumber)
VALUES (#ContractNumber)
Select #NewId = Id From [dbo].[Contracts] where ContractNumber = #ContractNumber
END
Opening the database:
pvConnectionString = "Server = Desktop-PC\\SQLEXPRESS; Database = PVDatabase; User ID = sa;
PASSWORD = *******; Trusted_Connection = True;";
try
{
pvConnection = new SqlConnection(pvConnectionString);
pvConnection.Open();
}
catch (Exception e)
{
databaseError = true;
}
Executing the command:
pvCommand = new SqlCommand("usp_InsertContract", pvConnection);
pvCommand.Transaction = pvTransaction;
pvCommand.CommandType = CommandType.StoredProcedure;
pvCommand.Parameters.Clear();
pvCommand.Parameters.Add(new SqlParameter("#ContractNumber", contractNumber));
SqlParameter pvNewId = new SqlParameter();
pvNewId.ParameterName = "#NewId";
pvNewId.DbType = DbType.Int32;
pvNewId.Direction = ParameterDirection.Output;
pvCommand.Parameters.Add(pvNewId);
try
{
sqlRows = pvCommand.ExecuteNonQuery();
if (sqlRows > 0)
Debug.Print("New Id Inserted = ",
pvCommand.Parameters["#NewId"].Value.ToString());
}
catch (Exception e)
{
Debug.Print("Insert Exception Type: {0}", e.GetType());
Debug.Print(" Message: {0}", e.Message);
}
}
I slightly modified your stored procedure (to use SCOPE_IDENTITY) and it looks like this:
CREATE PROCEDURE usp_InsertContract
#ContractNumber varchar(7),
#NewId int OUTPUT
AS
BEGIN
INSERT INTO [dbo].[Contracts] (ContractNumber)
VALUES (#ContractNumber)
SELECT #NewId = SCOPE_IDENTITY()
END
I tried this and it works just fine (with that modified stored procedure):
// define connection and command, in using blocks to ensure disposal
using(SqlConnection conn = new SqlConnection(pvConnectionString ))
using(SqlCommand cmd = new SqlCommand("dbo.usp_InsertContract", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// set up the parameters
cmd.Parameters.Add("#ContractNumber", SqlDbType.VarChar, 7);
cmd.Parameters.Add("#NewId", SqlDbType.Int).Direction = ParameterDirection.Output;
// set parameter values
cmd.Parameters["#ContractNumber"].Value = contractNumber;
// open connection and execute stored procedure
conn.Open();
cmd.ExecuteNonQuery();
// read output value from #NewId
int contractID = Convert.ToInt32(cmd.Parameters["#NewId"].Value);
conn.Close();
}
Does this work in your environment, too? I can't say why your original code won't work - but when I do this here, VS2010 and SQL Server 2008 R2, it just works flawlessly....
If you don't get back a value - then I suspect your table Contracts might not really have a column with the IDENTITY property on it.
Before changing stored procedure please check what is the output of your current one. In SQL Server Management run following:
DECLARE #NewId int
EXEC #return_value = [dbo].[usp_InsertContract]
N'Gary',
#NewId OUTPUT
SELECT #NewId
See what it returns. This may give you some hints of why your out param is not filled.
I had a similar problem and first closed the connection and then read the parameters and it worked fine.
you can use pvConnection.Close(); before read the output parameter
try
{
pvConnection = new SqlConnection(pvConnectionString);
pvConnection.Open();
}
catch (Exception e)
{
databaseError = true;
}
pvCommand = new SqlCommand("usp_InsertContract", pvConnection);
pvCommand.Transaction = pvTransaction;
pvCommand.CommandType = CommandType.StoredProcedure;
pvCommand.Parameters.Clear();
pvCommand.Parameters.Add(new SqlParameter("#ContractNumber", contractNumber));
SqlParameter pvNewId = new SqlParameter();
pvNewId.ParameterName = "#NewId";
pvNewId.DbType = DbType.Int32;
pvNewId.Direction = ParameterDirection.Output;
pvCommand.Parameters.Add(pvNewId);
try
{
sqlRows = pvCommand.ExecuteNonQuery();
pvConnection.Close();
if (sqlRows > 0)
Debug.Print("New Id Inserted = ",
pvCommand.Parameters["#NewId"].Value.ToString());
}
catch (Exception e)
{
Debug.Print("Insert Exception Type: {0}", e.GetType());
Debug.Print(" Message: {0}", e.Message);
}
}
Stored Procedure.........
CREATE PROCEDURE usp_InsertContract
#ContractNumber varchar(7)
AS
BEGIN
INSERT into [dbo].[Contracts] (ContractNumber)
VALUES (#ContractNumber)
SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]
END
C#
pvCommand.CommandType = CommandType.StoredProcedure;
pvCommand.Parameters.Clear();
pvCommand.Parameters.Add(new SqlParameter("#ContractNumber", contractNumber));
object uniqueId;
int id;
try
{
uniqueId = pvCommand.ExecuteScalar();
id = Convert.ToInt32(uniqueId);
}
catch (Exception e)
{
Debug.Print(" Message: {0}", e.Message);
}
}
EDIT: "I still get back a DBNull value....Object cannot be cast from DBNull to other types. I'll take this up again tomorrow. I'm off to my other job,"
I believe the Id column in your SQL Table isn't a identity column.
In your C# code, you are using transaction for the command.
Just commit the transaction and after that access your parameter value, you will get the value.
Worked for me. :)

Efficient Way to Update a lot of Rows from C#

I have a program where I open a SqlConnection, load up a list of objects, modify a value on each object, then update the rows in the SQL Server database. Because the modification requires string parsing I wasn't able to do with with purely T-SQL.
Right now I am looping through the list of objects, and running a SQL update in each iteration. This seems inefficient and I'm wondering if there is a more efficient way to do it using LINQ
The list is called UsageRecords. The value I'm updating is MthlyConsumption.
Here is my code:
foreach (var item in UsageRecords)
{
string UpdateQuery = #"UPDATE tbl810CTImport
SET MthlyConsumption = " + item.MthlyConsumption +
"WHERE ID = " + item.Id;
SqlCommand update = new SqlCommand(UpdateQuery, sourceConnection);
update.ExecuteNonQuery();
}
Try this instead:
string UpdateQuery = #"UPDATE tbl810CTImport SET MthlyConsumption = #consumption WHERE ID = #itemId";
var update = new SqlCommand(UpdateQuery, sourceConnection);
update.Parameters.Add("#consumption", SqlDbType.Int); // Specify the correct types here
update.Parameters.Add("#itemId", SqlDbType.Int); // Specify the correct types here
foreach (var item in UsageRecords)
{
update.Parameters[0].Value = item.MthlyConsumption;
update.Parameters[1].Value = item.Id;
update.ExecuteNonQuery();
}
It should be faster because:
You don't have to create the command each time.
You don't create a new string each time (concatenation)
The query is not parsed at every iteration (Just changes the parameters values).
And it will cache the execution plan. (Thanks to #JohnCarpenter from the comment)
You can either use
SqlDataAdapter - See How to perform batch update in Sql through C# code
or what I have previously done was one of the following:
Tear down the ID's in question, and re-bulkinsert
or
Bulk Insert the ID + new value into a staging table, and update the table on SQL server:
update u
set u.MthlyConsumption = s.MthlyConsumption
from tbl810CTImport u
inner join staging s on
u.id = s.id
In a situation like this, where you can't write a single update statement to cover all your bases, it's a good idea to batch up your statements and run more than one at a time.
var commandSB = new StringBuilder();
int batchCount = 0;
using (var updateCommand = sourceConnection.CreateCommand())
{
foreach (var item in UsageRecords)
{
commandSB.AppendFormat(#"
UPDATE tbl810CTImport
SET MthlyConsumption = #MthlyConsumption{0}
WHERE ID = #ID{0}",
batchCount
);
updateCommand.Parameters.AddWithValue(
"#MthlyConsumption" + batchCount,
item.MthlyConsumption
);
updateCommand.Parameters.AddWithValue(
"#ID" + batchCount,
item.MthlyConsumption
);
if (batchCount == 500) {
updateCommand.CommandText = commandSB.ToString();
updateCommand.ExecuteNonQuery();
commandSB.Clear();
updateCommand.Parameters.Clear();
batchCount = 0;
}
else {
batchCount++;
}
}
if (batchCount != 0) {
updateCommand.ExecuteNonQuery();
}
}
It should be as simple as this . . .
private void button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Server=YourServerName;Database=YourDataBaseName;Trusted_Connection=True");
try
{
//cmd new SqlCommand( "UPDATE Stocks
//SET Name = #Name, City = #cit Where FirstName = #fn and LastName = #add";
cmd = new SqlCommand("Update Stocks set Ask=#Ask, Bid=#Bid, PreviousClose=#PreviousClose, CurrentOpen=#CurrentOpen Where Name=#Name", con);
cmd.Parameters.AddWithValue("#Name", textBox1.Text);
cmd.Parameters.AddWithValue("#Ask", textBox2.Text);
cmd.Parameters.AddWithValue("#Bid", textBox3.Text);
cmd.Parameters.AddWithValue("#PreviousClose", textBox4.Text);
cmd.Parameters.AddWithValue("#CurrentOpen", textBox5.Text);
con.Open();
int a = cmd.ExecuteNonQuery();
if (a > 0)
{
MessageBox.Show("Data Updated");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
con.Close();
}
}
Change the code to suit your needs.

C# confirm table row has been deleted from database

I've written a method which will try and delete a row from a db table based on a primary key id. The problem i have is that the try block is always returning "Success" even if a record has already been deleted / or it doesn't exist.
public string delete_visit(int id)
{
string deleteResponse = null;
string cnn = ConfigurationManager.ConnectionStrings[connname].ConnectionString;
using (SqlConnection connection = new SqlConnection(cnn))
{
string SQL = string.Empty;
SQL = "DELETE FROM [" + dbname + "].[dbo].[" + tbname + "] WHERE VisitorNumber = #IDNumber ";
using (SqlCommand command = new SqlCommand(SQL, connection))
{
command.Parameters.Add("#IDNumber", SqlDbType.Int);
command.Parameters["#IDNumber"].Value = id;
try
{
connection.Open();
command.ExecuteNonQuery();
deleteResponse = "Success";
}
catch (Exception ex)
{
deleteResponse = "There was a problem deleting the visit from the database. Error message: " + ex.Message;
}
}
}
return deleteResponse;
}
I want to be able to tell if the row was affected. I can do this in SQL Server Management Studio like so:
DELETE FROM Visits
WHERE VisitorNumber=88;
IF ##ROWCOUNT = 0
PRINT 'Warning: No rows were updated';
So i want to know how do i plug in the ##ROWCOUNT bit into my c# so that i can tell if the row was deleted?
thanks
ExecuteNonQuery() returns an int, indicating how many rows were affected.
So:
int rowsAffected = command.ExecuteNonQuery();
if (rowsAffected == 0)
{
deleteResponse = "No rows affected";
}
The problem is that this number can be influenced based on what the query actually does. Executing triggers or calling stored procedures could mess with the output, changing the affected number of rows. If you really must, then first execute a query where you check that the record with the given ID exists.

how to generate unique max id from Data Base

I create a Applicant Registration form where Applicant Registration ID is generated by "Select Max(ID)...." Query. when this query is fetch out the MaxID from Data Base then i increment this ID by Plus one(+1) in this way i generate a Registration ID for all Applicant who register himself. But there is one problem occurred when i run my project from server and multiple clients (Approximately 10) Applicant try to Register then there is "primary key violation exception" occurred. There is 5 Insert Query is executed one-by-one after Max Query is executed
Code is Given Below
public long getUid()
{
try
{
string qry = "select isnull(max(Temp_Applicant_RegNo),0) as appregno FROM Temp_Reg";
if (cs.State == ConnectionState.Closed)
{
cs.Open();
}
cmd = new SqlCommand(qry, cs);
dr = cmd.ExecuteReader();
long cid = 0;
if (dr.Read())
{
cid = long.Parse(dr["appregno"].ToString());
cid++;
}
if (cs.State == ConnectionState.Open)
{
cs.Close();
}
return cid;
}
catch (Exception ex)
{
lbl_ErrorMsg.Text = ex.Message;
return 0;
}
}
protected void Save_btn_Click(object sender, EventArgs e)
{
SqlTransaction trn = null;
try
{
long Regid = getUid();
con.Open();
trn = con.BeginTransaction();
cmd = new SqlCommand("insert into....", con, trn);
cmd.Parameters.AddWithValue("#RegNo", Regid);
cmd.ExecuteNonQuery();
cmd = new SqlCommand("insert into....", con, trn);
cmd.Parameters.AddWithValue("#RegNo", Regid);
cmd.ExecuteNonQuery();
cmd = new SqlCommand("insert into....", con, trn);
cmd.Parameters.AddWithValue("#RegNo", Regid);
cmd.ExecuteNonQuery();
trn.Commit();
}
catch (Exception ex)
{
lbl_ErrorMsg.Text = ex.Message;
trn.Rollback();
}
}
Please give me suggestion that how can i generate Max ID for Applicant so that there is no chance to any duplication. Because i am working in live project.
for there i am using Asp.net C#
Don't do that, let the database generate the key for you when you insert a new row. Here is for example how to do it with SQL Server or MySQL. If you really want to do it on the client, use GUIDs as keys because you can generate them without consulting the database. There are some minor issues with GUIDs as keys because they are usually partially random and this may have negative performance effects on clustered indices, but for 99.9 % of all databases they are just fine.
Solution 1:
You can create a table with only one column, For example "GeneralID", and in your application control this Id to insert in another tables.
Solution 2:
Another solution is create a table and only one column, and a trigger to each table before insert to popule the id getting frmo the "Ids table" to insert.
Before we had auto incrementing columns we would have a table to hold the IDs. It would only have 2 columns IdType varchar(10) and NextId int. Then in a stored proc we would have something like:
while(1=1)
begin
select #nextId = nextId
from MyIds
where IdType=#IdType
update MyIds
set nextId = #nextId + 1
where IdType=#IdType
and nextId = #nextId
if(##ROWCOUNT > 0)
break;
end
select #nextId as nextId
Note that this would only update in the second statement if the nextId didn't change. If it did change it would try again.
I don't see when do you save the new value into Temp_Reg, but how if you save that value immediately after calculation, then you can safety update others tables:
public long getUid()
{
try
{
string qry = "select isnull(max(Temp_Applicant_RegNo),0) as appregno FROM Temp_Reg";
if (cs.State == ConnectionState.Closed)
{
cs.Open();
}
cmd = new SqlCommand(qry, cs);
dr = cmd.ExecuteReader();
long cid = 0;
if (dr.Read())
{
cid = long.Parse(dr["appregno"].ToString());
cid++;
}
UPDATE Temp_reg HERE !!!!
if (cs.State == ConnectionState.Open)
{
cs.Close();
}
return cid;
}
catch (Exception ex)
{
lbl_ErrorMsg.Text = ex.Message;
return 0;
}
}
Then you'll have to take this update into account inside the catch block of Save_btn_Click.
All of this if you can't use Autonumbers but If you can, use it.
If you could change your field Temp_Applicant_RegNo in an IDENTITY column, then you don't need to worry about the next number assigned to your table Temp_Reg. It is all a jopb made by your database.
All you need to know is what number has been assigned and use that number in your subsequent inserts.
This could be easily done using the SELECT SCOPE_IDENTITY() after the insert in your
protected void Save_btn_Click(object sender, EventArgs e)
{
SqlTransaction trn = null;
try
{
con.Open();
trn = con.BeginTransaction();
cmd = new SqlCommand("insert into....; SELECT SCOPE_IDENTITY()", con, trn);
int Regid = Convert.ToInt32(cmd.ExecuteScalar());
cmd = new SqlCommand("insert into....", con, trn);
cmd.Parameters.AddWithValue("#RegNo", Regid);
cmd.ExecuteNonQuery();
cmd = new SqlCommand("insert into....", con, trn);
cmd.Parameters.AddWithValue("#RegNo", Regid);
cmd.ExecuteNonQuery();
trn.Commit();
}
catch (Exception ex)
{
lbl_ErrorMsg.Text = ex.Message;
trn.Rollback();
}
The trick is possible adding the SELECT SCOPE_IDENTITY() as a second query to the first insert and then call ExecuteScalar. ExecuteScalar executes the queries and then returns the value of the first column in the first row of the last query executed.

C# Update statment failed Error: _COMPlusExceptionCode = -532459699

I have a method which updates a table as below :
public static Boolean updateRequest(String _VUserName, DateTime newToDate)
{
SqlConnection conn = getConnection();
SqlCommand command = new SqlCommand();
command.CommandText = "UPDATE Requests SET [To] = #ToDate FROM Requests INNER JOIN "+
"VUsers ON Requests.UserRef = VUsers.VUserID WHERE (VUsers.VUserName = #VUserName)";
command.Parameters.AddWithValue("#ToDate", newToDate);
command.Parameters.AddWithValue("#VUserName", _VUserName);
conn.Open();
try
{
command.ExecuteNonQuery();
return true;
}
catch (Exception)
{
return false;
}
conn.Close();
}
but it failed with _COMPlusExceptionCode = -532459699 exception
any help?
Please check the following link "SQL Server refusing to add a record because it didn't conform to table column specifications"
It looks like it has to do with your update statement. Rather rewrite it like this.
"UPDATE Requests SET [To] = #ToDate WHERE ...

Categories