I've been advised to replace my code with SqlParameter to avoid SQL injection as a security issue but with my limited understanding. I tried implementing it but I'm faced with an error:
Must Declare Scalar Variable
I've tried the other suggestions of other threads about implementing a new parameter for every insertion instead of replacing the value of parameter for every entry.
String query = "INSERT INTO EmpInfo(EmpYear, EmpStatus, LName, FName, JobTitle, EmpPay, EmpDoB, EmpSex, EmpAddr, EmpCity, EmpState, EmpZIP, EmpCountry, EmpEAddr, EmpTelNo, EmpMobileNo, EmpDate) " +
"VALUES('"+EmpYear+"', #EmpStatus, #LName, #FName, #JobTitle, #EmpPay, #EmpDoB, #EmpSex, #EmpAddr, #EmpCity, #EmpState, #EmpZIP, #EmpCountry, #EmpEAddr, #EmpTelNo, #EmpMobileNo, getdate())";
String query2 = "INSERT INTO AccountInfo(LName, FName, EmpTemplate, AccountType, EmpStatus, EmpDate) " +
"VALUES (#LName, #FName, #EmpTemplate, #AccountType, #EmpStatus, GetDate())";
using (SqlConnection connection = new SqlConnection("Data Source=RB-DESKTOP;Initial Catalog=TimeDB;Persist Security Info=True;User ID=sa;Password=bautista7"))
{
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT MAX(EmpID) FROM EmpInfo";
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Close();
SqlCommand command = new SqlCommand(query, cmd.Connection);
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpYear", Value = EmpYear });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpStatus", Value = "Active" });
command.Parameters.Add(new SqlParameter() { ParameterName = "#LName", Value = regLname_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#FName", Value = regFname_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#JobTitle", Value = "NULL" });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpPay", Value = PayType_cb.SelectedItem.ToString() });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpDoB", Value = regDob_dtp.Value.Date });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpSex", Value = gender });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpAddr", Value = regAddr_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpCity", Value = regCity_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpState", Value = regState_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpZIP", Value = regZip_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpCountry", Value = regCountry_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpEAddr", Value = regEmail_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpTelNo", Value = regTel_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpMobileNo", Value = regMob_text.Text });
command.ExecuteNonQuery();
command.Parameters.Clear();
SqlCommand command2 = new SqlCommand(query2, cmd.Connection);
command.Parameters.AddWithValue("#LName", regLname_text.Text);
command.Parameters.AddWithValue("#FName", regFname_text.Text);
command.Parameters.AddWithValue("#EmpTemplate", template);
command.Parameters.AddWithValue("#AccountType", AcctType_cb.SelectedItem.ToString());
command.Parameters.AddWithValue("#EmpStatus", "Active");
command.ExecuteNonQuery();
command.Parameters.Clear();
You are using the command variable twice instead of command2 after you create command2. You get the error because you cleared command of all parameters, then add parameters (which do not match the existing query) and then execute ExecuteNonQuery which then throws the error.
Change 2nd execution statement / command like so, notice that after the creation of command2 it is now also used instead of reusing command.
SqlCommand command2 = new SqlCommand(query2, cmd.Connection);
command2.Parameters.AddWithValue("#LName", regLname_text.Text);
command2.Parameters.AddWithValue("#FName", regFname_text.Text);
command2.Parameters.AddWithValue("#EmpTemplate", template);
command2.Parameters.AddWithValue("#AccountType", AcctType_cb.SelectedItem.ToString());
command2.Parameters.AddWithValue("#EmpStatus", "Active");
var numberOfRecordsInserted = command2.ExecuteNonQuery();
// value of numberOfRecordsInserted should be 1
Also when you are done using a SqlCommand you can dispose of it, there is no need to call SqlCommand.Parameters.Clear() unless you plan on reusing the exact same SqlCommand instance which you are not (at least not in the posted code).
I think you should try simplify your logic first. I found several weird things.
query has "VALUES('"+EmpYear+"', I think you want #EmpYear because you also have
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpYear", Value = EmpYear });
Additionally
SqlCommand cmd = new SqlCommand(query, connection);
//^^^ here you use insert query
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT MAX(EmpID) FROM EmpInfo"; // But here you change it for a SELECT?
// Then you execeute a DataReader but you close it before save the result.
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Close();
//Then create the insert command again
SqlCommand commad = new SqlCommand(query, cmd.Connection);
....
// clear command, I guess you want reuse it
command.Parameters.Clear();
// now create command 2 is OK
SqlCommand command2 = new SqlCommand(query2, cmd.Connection);
// ^^^ second insert query
// but add parameteres to command NOT OK
command.Parameters.AddWithValue("#LName", regLname_text.Text);
Consider this code....
WHY is it failing telling me that the #PI_CDID parameter value is not set when trying to execute the stored procedure?
Console.WriteLine("Database Opened!");
SqlCommand cmd = new SqlCommand("P_IOU_Track", conn);
cmd.Parameters.Add(new SqlParameter("#PI_CDID", ICDID)); // parameter is added here
cmd.Parameters.Add(new SqlParameter("#PI_Title", ITitle));
cmd.Parameters.Add(new SqlParameter("#PI_Duration", IDuration));
cmd.Parameters.Add(new SqlParameter("#PI_CDNo", ICDNo));
cmd.Parameters.Add(new SqlParameter("#PI_TNo", ITNo));
foreach (SqlParameter p in cmd.Parameters )
{
Console.WriteLine("Parameter , {0} , Value --> {1} ",p.ParameterName, p.Value.ToString());
}
// Add output param
SqlParameter NextTID = new SqlParameter("#PO_NextTID", SqlDbType.BigInt);
NextTID.Direction = ParameterDirection.Output;
cmd.Parameters.Add(NextTID);
// Execute procedure
cmd.ExecuteNonQuery();
You forgot cmd.CommandType = CommandType.StoredProcedure
I have a long running stored procedure that returns multiple results.
I'd like to iterate the results asynchronously and grab results as they are ready (AS THEY ARE AVAILABLE).
ExecuteReaderAsync with some WaitOne logic? (never used this so any example is appreciated)
Is this possible?
private IEnumerable<DataTable> validationResultSets(string MOName, DateTime StartDate, DateTime EndDate, string FilePath)
{
DataTable d;
using (SqlConnection conn =
new SqlConnection(connString))
{
conn.Open();
using (cmd = new SqlCommand("dbo.sp_ValidateAcceptanceFile", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter
{
ParameterName = "#MOName",
Value = MOName,
SqlDbType = SqlDbType.VarChar,
Size = 255
});
cmd.Parameters.Add(new SqlParameter
{
ParameterName = "#StartDate",
Value = StartDate,
SqlDbType = SqlDbType.DateTime
});
cmd.Parameters.Add(new SqlParameter
{
ParameterName = "#EndDate",
Value = EndDate,
SqlDbType = SqlDbType.DateTime
});
cmd.Parameters.Add(new SqlParameter
{
ParameterName = "#FilePath",
Value = FilePath,
SqlDbType = SqlDbType.VarChar,
Size = 500
});
//IDataReader rdr = cmd.ExecuteReader();
IDataReader rdr = cmd.BeginExecuteReader(); //??
try
{
do
{
d = new DataTable();
d.Load(rdr);
yield return d;
} while (!rdr.IsClosed);
}
finally
{
rdr.Close();
rdr.Dispose();
}
}
}
}
You are mixing concepts. A procedure returning multiple results is not related in any way to MARS. A procedure returning multiple results can be invoked asynchronously, note that your async call will complete as soon as the first fragment of the result has returned from the server and from there on you read the results just like in the sync code.
I have this update:
sql = "UPDATE table SET prioridade = #prioridade, situacao = #sit , responsavel = #resp , previsao_termino = #previsao, chamado_designado = #designado WHERE id = #id";
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new MySqlParameter("#prioridade", MySqlDbType.Int32)).Value = ch.Prioridade_ID;
cmd.Parameters.Add(new MySqlParameter("#sit", MySqlDbType.Int32)).Value = ch.Situacao_ID;
cmd.Parameters.Add(new MySqlParameter("#resp", MySqlDbType.Int32)).Value = ch.Responsavel_ID;
cmd.Parameters.Add(new MySqlParameter("#previsao", MySqlDbType.Date)).Value = ch.Previsao_Termino;
cmd.Parameters.Add(new MySqlParameter("#designado", MySqlDbType.Int32)).Value = ch.Chamado_Designado;
cmd.Parameters.Add(new MySqlParameter("#id", MySqlDbType.Int32)).Value = ch.ID;
_dal.Executar(cmd);
the value of ch.Previsao_Termino is equal to 31/05/2013 the field previsao_termino is a date type. When it will make the update it throws me an error saying that:
Wrong Value for the field previsao_termino 0031-05-2013.
Where did that 00 came from ? Maybe the connector ? I updated my connector to a new version, also i updated my VisualStudio 2010 to VisualStudio 2012 and sinced I changed that, i've got a lot of problems u.u.
Answer provided by #EdGibbs
When working with MySqlCommand.Parameters the variable you are passing as its value, MUST be the same type that you set the parameter. e.g
MySqlCommand.Parameter.Add(new MySqlParameter("#ParamName", MySqlDataType.DateTime)).value = dtValue
the varaible dtvalue MUST BE DATETIME TYPE, if like me you are using string, then you should use the following conversion.
DateTime.ParseExact(ch.Previsao_Termino, 'dd/MM/yyyy', null)
i try to use erpCtx.Executecommand but i doesn't have method of executecommand. i think that i must add dll in Reference to show executeCommand?
i need : int rowsAffected = engCtx.ExecuteCommand("insert into xtable Values({0},{1},{2},{3})", engArray[0], engArray1, engArray[2], engArray[3]);
In the Entity Framework, it's called ExecuteStoreCommand.
Something like this?
using (var db = new DAL.CrawlerDalEntities())
{
db.Connection.Open();
using (var cmd = db.Connection.CreateCommand())
{
cmd.CommandTimeout = storedProcedureDefaultTimeout;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "CrawlerDalEntities.PerformBackup";
cmd.Parameters.Add(new EntityParameter
{
ParameterName = "fileName",
Value = fileName,
DbType = DbType.String
});
cmd.Parameters.Add(new EntityParameter
{
ParameterName = "backupName",
Value = backupName,
DbType = DbType.String
});
cmd.ExecuteNonQuery();
}
db.Connection.Close();
}
DataContext.ExecuteCommand is in:
Namespace: System.Data.Linq
Assembly: System.Data.Linq (in System.Data.Linq.dll)
Source