I have been trying to find a solution to this problem but so far nothing worked.
private void Insert()
{
string ConnectionStringAccess = Provider=Microsoft.ACE.OLEDB.12.0;Data Source=###Jet OLEDB:Database Password=###;
string query2 = "Select ##Identity";
int id = -1;
string Query = "INSERT INTO tblTable (EmpNo, Name) VALUES (132, 'TestName');";
OleDbConnection con = new OleDbConnection(ConnectionStringAccess);
OleDbCommand cmd = new OleDbCommand(Query, con);
try
{
con.Open();
if (cmd.ExecuteNonQuery() == 1)//the insert succeded
{
cmd.CommandText = query2;
id = Convert.ToInt32(cmd.ExecuteScalar());
}
}
catch (Exception ex)
{
//log the ex
}
finally
{
con.Dispose();
con.Close();
}
}
Each time I use the above method I always get a return of 0 in "id". What am I doing wrong? I tried using a different connection string or another way to get latest identifier:
Provider=Microsoft.Jet.OLEDB.4.0;
SCOPE_IDENTITY()
but again nothing. The Access db is 2003 or older (not sure exactly).
The ms access db is 2003 or older (not sure exactly)
I was able to recreate your issue with an Access 97 database. SELECT ##IDENTITY worked correctly with an Access 2000 database file (even when run from the same OleDbCommand object as the INSERT), but it always returned zero when run against an Access 97 database.
It appears that you will need to upgrade your database file to a newer version if you want SELECT ##IDENTITY to work.
You are using the same command object for both the insert and retrieval of ##identity.
According to this article you should create a separate command object for retrieving the ##identity value:
http://support.microsoft.com/kb/815629
Also, just to verify, the table you are inserting to does have an auto increment column, is that correct? If not, ##identity would not return anything.
Create two different commands for your queries, execute non query then execute scalar. It will return the first column of the first row in the result set returned by the query and it should be the id you're looking for.
private void Insert()
{
string ConnectionStringAccess = Provider=Microsoft.ACE.OLEDB.12.0;Data Source=###Jet OLEDB:Database Password=###;
int id = -1;
string Query = "INSERT INTO tblTable (EmpNo, Name) VALUES (132, 'TestName')";
string Query2 = "SELECT ##Identity";
OleDbConnection con = new OleDbConnection(ConnectionStringAccess);
OleDbCommand cmd = new OleDbCommand(Query, con);
OleDbCommand cmd2 = new OleDbCommand(Query2, con);
try
{
con.Open();
cmd.ExecuteNonQuery();
id = (int)cmd2.ExecuteScalar();
}
catch (Exception ex)
{
//log the ex
}
finally
{
con.Dispose();
con.Close();
}
}
thanks for all the responses. I found out what the problem was. Apparently the access file is very old, 1997 to be exact and that was the problem. As soon as a tried a new access 2010 file it worked.
Thanks again
My soluce with my very older databases (VB6 and ACCESS)
With VB NET and before upgrade Database to 4.
'MyInsertCommand.CommandText = "Select ##Identity" Don't work with old Access database
MyInsertCommand.CommandText = "SELECT TOP 1 ME_idn FROM MESURE ORDER BY ME_idn Desc"
Dim MyInsertIdn As Integer = MyInsertCommand.ExecuteScalar()
Related
I have looked around and I am still confused on how to get the last inserted ID. I added the statment SELECT LAST_INSERT_ID(); at the end of mysql statement i am executing. I am storing the value in prID = Convert.ToInt32(cmd.ExecuteScalar()); This command is creating two instances in my database. I am pretty sure I need to separate these two statements but unsure how to while still getting the last ID.
try
{
Console.WriteLine("Connecting to MySQL...");
conn.Open();
string sql = "INSERT INTO pull_requests (repoID, branchID, fileID, prStatus, prComments) VALUES (#rID, #bID, #fID, #prS, #prC); SELECT LAST_INSERT_ID();";
MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("#rID", RI);
cmd.Parameters.AddWithValue("#bID", BI);
cmd.Parameters.AddWithValue("#fID", FI);
cmd.Parameters.AddWithValue("#prS", 0);
cmd.Parameters.AddWithValue("#prC", comment);
prID = Convert.ToInt32(cmd.ExecuteScalar());
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
conn.Close();
You need to only call cmd.ExecuteNonQuery() to execute the insert statement. On the return, the cmd object will have its .LastInsertedId property populated for you.
Like this:
try
{
Console.WriteLine("Connecting to MySQL...");
conn.Open();
string sql = "INSERT INTO pull_requests (repoID, branchID, fileID, prStatus, prComments) VALUES (#rID, #bID, #fID, #prS, #prC);";
MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("#rID", RI);
cmd.Parameters.AddWithValue("#bID", BI);
cmd.Parameters.AddWithValue("#fID", FI);
cmd.Parameters.AddWithValue("#prS", 0);
cmd.Parameters.AddWithValue("#prC", comment);
cmd.ExecuteNonQuery();
long lastId = cmd.LastInsertedId;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
conn.Close();
Use the MySqlCommand.LastInsertedId property after executing the query.
Typically, the SELECT last_insert_id() is executed separately, immediately after the INSERT is executed, on the same connection. The result of last_insert_id() is connection specific, so you do not need to worry about other clients "overwriting" yours.
You can even reuse the same command with just cmd.CommandText = "SELECT last_insert_id()";
...but as others have pointed out, and a quick web search has clarified for me, it looks like the MySQL .Net connector you are using already provides that without a second query.
try
{
OleDbConnection myConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\HP8200\\Desktop\\ELISA2014Data.mdb ;Persist Security Info=False;");
myConnection.Open();
// Create Oledb command to execute particular query
OleDbCommand myCommand = new OleDbCommand();
myCommand.Connection = myConnection;
// Query to create table with specified data columne
myCommand.CommandText = "CREATE TABLE UXZona([IDZona] int, [Morada] text)";
//myCommand.ExecuteNonQuery();
MessageBox.Show("Tabela criada");
}
catch
{
OleDbConnection myConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\HP8200\\Desktop\\ELISA2014Data.mdb ;Persist Security Info=False;");
myConnection.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO UXZona (IDZona, Morada) VALUES ('" +
transaction.UnloadPlaceAddress.AddressID + "','" +
transaction.UnloadPlaceAddress.AddressLine2 + "')";
cmd.ExecuteNonQuery();
MessageBox.Show("Dados inseridos");
}
I need to insert data into the database but it isn't working. I launch the program and there are no errors, I do everything but when I check the database the table is empty.
UPDATE
Now when i launch the program I have this error:
"System.InvalidOperationException: 'ExecuteNonQuery: Connection property has not been initialized." on cmd.ExecuteNonQuery();
There are a number of things wrong! I give below corrected code:
try
{
bool success = false;
using (var myConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\HP8200\\Desktop\\ELISA2014Data.mdb ;Persist Security Info=False;"))
{
// Create Oledb command to execute particular query
using (var myCommand = new OleDbCommand())
{
myCommand.Connection = myConnection;
// Query to create table with specified data columne
//myCommand.CommandText = "CREATE TABLE UXZona([IDZona] int, [Morada] text)";
//myCommand.ExecuteNonQuery();
//MessageBox.Show("Tabela criada");
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO UXZona (IDZona, Morada) VALUES (#id, #morada)";
var param = cmd.CreateParameter();
param.ParameterName = "#id";
param.OleDbType = OleDbType.Integer;
param.Value = transaction.UnloadPlaceAddress.AddressID;
cmd.Parameters.Add(param);
param = cmd.CreateParameter();
param.ParameterName = "#morada";
param.OleDbType = OleDbType.VarChar;
param.Value = transaction.UnloadPlaceAddress.AddressLine2;
cmd.Parameters.Add(param);
myConnection.Open();
if (cmd.ExecuteNonQuery() == 1)
{
success = true;
}
}
}
if (success)
{
MessageBox.Show("Dados inseridos");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
By way of explanation. I have commented out (but not deleted) all references to creating the table. Table creation and table insertion should be in two different routines. Normally you only create a table once, but insert is probably called many times.
I have placed the OleDbConnection and OleDbCommand within using loops. This is good practice, as they both implement IDisposable. Writing your code like this means that the Garbage Collector (GC) knows immediately that it can safely dispose of the objects after use.
I have changed the insert statement such that it takes parameters. This is highly recommended practice to safeguard against SQL Injection (if you do not know what this is please Google it). In fact Access is relatively immune from the worst forms of SQL Injection, because it rejects any command that contains multiple statements, but please get into good habits. With time you will progress to other databases which do not have this restriction.
I deliberately wait before opening the connection until just before it is needed. Connections consume resources, so it is good practice to use them as sparingly as possible. Also for this reason, I have moved your success message outside of the using loops. This means that the cleanup of resources is not waiting for the user to click OK in the message box.
Finally try catch is all well and good, but normally you want to know why the error occurred. Hence you add (Exception ex) to catch so that you can find the reason.
PS What I forgot to mention. In your original INSERT, you were surrounding both VALUES with single quotes. Only use single quotes for strings/text. Integers and other numbers require no quotes. If you quote them, the database will treat it as a string and you will get a data type error.
I am populating a text box with the returned value of a function, but it doesn't work if I run the sql code inside the function. I can remove the sql related code and it works. so i'm stumped.
And by "doesn't work" i mean that the text box never gets populated with anything. it remains blank.
thanks
public string CreateResident()
{
string result = "hmm";
SqlConnection sqlConnection = new SqlConnection("Server=DELLXPS\\SQLEXPRESS; Initial Catalog=Warren_SEINDATASYSTEMS; Integrated Security=true;");
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "INSERT INTO [dbo].[NewUsers]([ResidentAccountNumber],[ResidentName],[ResidentAddress],[NumberOfVisitors],[TempPass],[Role])VALUES(#ResidentAccountNumber,#ResidentName,#ResidentAddress,#NumberOfVisitors,(select cast((Abs(Checksum(NewId()))%10) as varchar(1)) + char(ascii('a')+(Abs(Checksum(NewId()))%25)) + char(ascii('A')+(Abs(Checksum(NewId()))%25)) + left(newid(),5)),'resident')";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
SqlParameter ResidentAccountNumber = new SqlParameter();
ResidentAccountNumber.ParameterName = "#ResidentAccountNumber";
ResidentAccountNumber.Value = txtboxResidenetAccountNumber.Text.Trim();
cmd.Parameters.Add(ResidentAccountNumber);
SqlParameter ResidentName = new SqlParameter();
ResidentName.ParameterName = "#ResidentName";
ResidentName.Value = txtboxResidentName.Text.Trim();
cmd.Parameters.Add(ResidentName);
SqlParameter ResidentAddress = new SqlParameter();
ResidentAddress.ParameterName = "#ResidentAddress";
ResidentAddress.Value = txtboxResidentAddress.Text.Trim();
cmd.Parameters.Add(ResidentAddress);
SqlParameter NumberOfVisitors = new SqlParameter();
NumberOfVisitors.ParameterName = "#NumberofVisitors";
NumberOfVisitors.Value = txtboxNumberOfVisitors.Text.Trim();
cmd.Parameters.Add(NumberOfVisitors);
try
{
sqlConnection.Open();
result = (string)cmd.ExecuteScalar();
sqlConnection.Close();
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
}
protected void btnCreateResident_Click(object sender, EventArgs e)
{
txtboxTempPassword.Text = CreateResident();
}
Your SQL is wrong and you have a lot of problems but I want to show you a way to make your code more readable. Format it like this:
cmd.CommandText = #"INSERT INTO [dbo].[NewUsers] ([ResidentAccountNumber],[ResidentName],[ResidentAddress], NumberOfVisitors],[TempPass], Role])
VALUES(
#ResidentAccountNumber,
#ResidentName,
#ResidentAddress,
#NumberOfVisitors,
(select cast((Abs(Checksum(NewId()))%10) as varchar(1)) + char(ascii('a')+(Abs(Checksum(NewId()))%25)) + char(ascii('A')+(Abs(Checksum(NewId()))%25)) + left(newid(),5)),
'resident')";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
We know that a select in a VALUES constructor is not legal so that is one problem.
Also having a SELECT without a from seems strange -- did you copy your code correctly?
You are using ExecuteScalar -- do you know what that does? It shouldn't include a query that includes INSERT query.
I'm guessing you probably want a stored procedure.
I would suggest do not write query in C# code, you must use Stored Procedure for the same purpose.
If you want your query to return some id, primary key or some value then you must write query for that after your insert query.
you can use the following keywords in your select query,if you want to return id from table.
SCOPE_IDENTITY returns the last IDENTITY value inserted into an IDENTITY column in the same scope.
IDENT_CURRENT returns the last identity value generated for a specific table in any session and any scope.
##IDENTITY returns the last identity value generated for any table in the current session, across all scopes.
If you want to return only one record then use ExecuteScalar else you can use ExecuteReader.
If your only purpose is to insert data into the table then you should use ExecuteNonQuery.
With the help of comments I went with ExecuteReader instead of the ExecuteScaler. And changed the statement to return a value
INSERT INTO [table] ([fields]) OUTPUT Inserted.MyColumn VALUES(values)
C# Code:
reader = cmd.ExecuteReader();
try
{
while (reader.Read())
{
result = reader[0].ToString();
}
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
doubles quotes dont work so you have to type 'some value' to actually do variable comparisons when doing direct execution of SQL statements.
Problem is that now when I execute the SQL statement from ASP.NET code I dont seem to be getting any readings...I am not even getting errors :S....
I HAVE tried executing the SQL statement on its own, and it does work.
public static string testExi(string localIncidentNum)
{
try
{
string query = "SELECT TOP 1 UniqueColID From DBNAME WHERE LocalIncidentNum = #localIncidentNum ORDER BY [version] DESC";
DataTable dt = new DataTable();
SqlConnection connection = new SqlConnection(connectionStr);
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#localIncidentNum", localIncidentNum);
connection.Open();
SqlDataAdapter adp = new SqlDataAdapter(command);
adp.Fill(dt);
connection.Close();
command.Dispose();
connection.Dispose();
if (dt.Rows.Count != 0)
{
string UniqueColID = dt.Rows[0]["UniqueColID"].ToString();
return UniqueColID;
}
else
{
return null;
}
string some = dt.Rows[0]["UniqueColID"].ToString();
return some;
}
catch (Exception err)
{
Global.tmpmsg = " Updating follow up was not successful. " + err.ToString();
return null;
}
}
If I hardcode an incident value in the SELECT statement it works but if I hardcode the incident value in .addwithvalue, it doesn't work.
command.Parameters.AddWithValue("#localIncidentNum", "12-023696");
Double check your sql statement:
SELECT TOP 1 UniqueColID From WHERE LocalIncidentNum = #localIncidentNum ORDER BY [version] DESC
From Where?
Edit
In observance of your change, best to always be as accurate as possible when describing your problem. Leaving out something like the table name of a sql statement is very misleading.
Perhaps add a datatype to your command parameter. I believe that you are not getting anything because it may be timing out on the command.
command.Parameters.AddWithValue("#localIncidentNum", localIncidentNum);
command.Parameters[0].SqlDbType = SqlDbType.VarChar;
I found a similar problem here, also using Varchar:
AddWithValue without DBType causing queries to run slowly
I solved it. The problem was that I (for some reason) needed to put the full path of the table before the table name in sql code when executing it from C sharp file:
SELECT TOP 2 [DB name].[dbo]. [table name]
i have a question if you please help me i have an error
Must declare the scalar variable
"#Deitails".
and i can not find out whats the problem since i am not aware what Scalar is about
var sqlCon = new
SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
// GET CONFERENCE ROLE ID
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlCon;
cmd.CommandText = "select Conference_Role_ID from AuthorPaper
where Paper_ID = #PaperId";
cmd.Parameters.AddWithValue("#PaperId",
paperId);
cmd.Connection.Open();
string ConferenceRoleId = cmd.ExecuteScalar().ToString();
cmd.Connection.Close();
cmd.Dispose();
string query2 = #"insert into
ReviewPaper(Overall_Rating,Paper_id,Conference_role_id,Deitails)
values(0,#paperId,#ConferenceRoleId,#Deitails);select
SCOPE_IDENTITY() as RPID";
cmd = new SqlCommand(query2, sqlCon);
cmd.Parameters.AddWithValue("#paperId",
paperId);
cmd.Parameters.AddWithValue("#ConferenceRoleId",
ConferenceRoleId);
string ReviewPaperId;
try
{
cmd.Connection.Open();
ReviewPaperId = cmd.ExecuteScalar().ToString();
cmd.Connection.Close();
}
catch (Exception ee) { throw ee; }
finally { cmd.Dispose(); }
thanks
You have a SQL query with a parameter named Details, but you forgot to add the parameter.
You have a line of code which says
string query2 = #"insert into ReviewPaper(Overall_Rating, Paper_id,
Conference_role_id, Deitails) values (0,#paperId,#ConferenceRoleId,#Deitails);
select SCOPE_IDENTITY() as RPID";
You provide the parameters #paperId, #ConferenceRoleId and #Deitails for the values for the insert statement. Later you specify the value for the first two parameters, but not #Deitails:
cmd.Parameters.AddWithValue("#paperId", paperId);
cmd.Parameters.AddWithValue("#ConferenceRoleId", ConferenceRoleId);
You need to add a similar line to add the value for #Deitails so that SQL server knows what to do with it. The error you are getting is coming from SQL server because by not adding a value for #Deitails in your C# code, it is not being declared for you in the SQL code which is sent to the server.
To answer your other question, 'Scalar' in this case means that the variable #Deitails represents a single value.