The parameterized query expects the parameter , which was not supplied - c#

in my MVC application there is a method
public void insertAddress(AddressModel address)
{
var connection = OpenConnection();
var command = connection.CreateCommand();
command.CommandText = "insert into Adres (AddressLine_1,AddressLine_2,Postcode,Town,DateMovedIn,Id) values (#AddressLine_1, #AddressLine_2, #Postcode, #Town,#DateMovedIn,#Id)";
AddParameterString(command, "#AddressLine_1", address.AddressLine_1);
AddParameterString(command, "#AddressLine_2", address.AddressLine_2);
AddParameterString(command, "#Postcode", address.Postcode);
AddParameterString(command, "#Town", address.Town);
AddParameterString(command, "#DateMovedIn", address.DateMovedIn.ToString("yyyyMMdd"));
AddParameterInt(command, "#Id", address.Id);
command.ExecuteNonQuery();
}
AddressLine2 in model is not required. When user is not submitting AddressLine2 I get error:
The parameterized query '(#AddressLine_1 nvarchar(3),#AddressLine_2
nvarchar(4000),#Postc' expects the parameter '#AddressLine_2', which
was not supplied.
How can I modify this method to work in both cases - user submitting AddressLine2 and user not submitting AddressLine2?

public void insertAddress(AddressModel address)
{
var connection = OpenConnection();
var command = connection.CreateCommand();
command.CommandText = "insert into Adres (AddressLine_1,AddressLine_2,Postcode,Town,DateMovedIn,Id) values (#AddressLine_1, #AddressLine_2, #Postcode, #Town,#DateMovedIn,#Id)";
command.Parameters.Add(new SqlParameter { ParameterName = "#AddressLine_1", Value = address.AddressLine_1 });
if (address.AddressLine_2 == null)
{
command.Parameters.Add(new SqlParameter { ParameterName = "#AddressLine_2", Value = DBNull.Value });
}
else
{
command.Parameters.Add(new SqlParameter { ParameterName = "#AddressLine_2", Value = address.AddressLine_2 });
}
command.Parameters.Add(new SqlParameter { ParameterName = "#Postcode", Value = address.Postcode });
command.Parameters.Add(new SqlParameter { ParameterName = "#Town", Value = address.Town });
command.Parameters.Add(new SqlParameter { ParameterName = "#DateMovedIn", Value = address.DateMovedIn.ToString("yyyyMMdd") });
command.Parameters.Add(new SqlParameter { ParameterName = "#Id", Value = address.Id });
command.ExecuteNonQuery();
}

This happens when a parameter value is null. To fix it you need to set parameter value to DbNull when the property is null.
void AddParameterString(SqlCommand command, string parameterName, string parameterValue)
{
var param = command.Parameters.Add(parameterName, SqlDbType.NVarChar, 4000);
param.Value = String.IsNullOrEmpty(parameterValue) ? (object) DbNull.Value : (object) parameterValue;
}

You can simply use Null-coalescing operator (??):
AddParameterString(command, "#AddressLine_2", address.AddressLine_2 ?? Convert.DBNull);

Related

Stored Procedure error when called from Entity Framework

I'm trying to build a simple project that will run my stored procedure .
When I execute the SP through SQL-Server it works fine :
EXECUTE RunSSISPackage1
#folder_name1 = N'SSIS projects',
#project_name1=N'CalculateReports',
#package_name1=N'CalculateReports.dtsx',
#param1 = N'2017-04-01 00:00:00',
#param1name = N'startDate'
My controller:
public IActionResult Test()
{
using (var cmd = _context.Database.GetDbConnection().CreateCommand())
{
cmd.CommandText = "RunSSISPackage";
cmd.CommandType = CommandType.StoredProcedure;
// set some parameters of the stored procedure
cmd.Parameters.Add(new SqlParameter("#package_name1", SqlDbType.NVarChar)
{
Value = "N'CalculateReports.dtsx'"
});
cmd.Parameters.Add(new SqlParameter("#folder_name1", SqlDbType.NVarChar)
{
Value = "N'SSIS projects'"
});
cmd.Parameters.Add(new SqlParameter("#project_name1", SqlDbType.NVarChar)
{
Value = "N'CalculateReports.dtsx'"
});
cmd.Parameters.Add(new SqlParameter("#param1", SqlDbType.NVarChar)
{
Value = "N'2017-04-01 00:00:00'"
});
cmd.Parameters.Add(new SqlParameter("#param1name", SqlDbType.NVarChar)
{
Value = "N'startDate'"
});
if (cmd.Connection.State != ConnectionState.Open)
cmd.Connection.Open();
cmd.ExecuteNonQuery();
return View();
}
}
I'm getting an error :
Cannot access the package or the package does not exist. Verify that the package exists and that the user has permissions to it.
This error occurs when the parameters of package_name\folder_name\project_name is not sent correctly.
How can I pass prefix values as a parameter?
You don't need the N'...' wrap in your code, that's only a SQL Server thing for unicode conversion. For example, see this. So when you're doing that, you're actually passing the package name of N'CalculateReports.dtsx' which obviously doesn't exist.
Instead, do this Value = "CalculateReports.dtsx", for example:
cmd.Parameters.Add(new SqlParameter("#package_name1", SqlDbType.NVarChar)
{
Value = "CalculateReports.dtsx"
});
cmd.Parameters.Add(new SqlParameter("#folder_name1", SqlDbType.NVarChar)
{
Value = "SSIS projects"
});
cmd.Parameters.Add(new SqlParameter("#project_name1", SqlDbType.NVarChar)
{
Value = "CalculateReports.dtsx"
});
cmd.Parameters.Add(new SqlParameter("#param1", SqlDbType.NVarChar)
{
Value = "2017-04-01 00:00:00"
});
cmd.Parameters.Add(new SqlParameter("#param1name", SqlDbType.NVarChar)
{
Value = "startDate"
});

error with addwithvalue sql parameter

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);

How to create SqlParameterCollection with multiple parameters?

I am trying to create a SqlParameterCollection, but gives error while adding some SqlParameter in sp.Add() method.
Please help me how to add parameter and how to pass it to my another function where I declare a SqlConnection and SqlCommand.
SqlParameterCollection sp = null;
sp.Add(new SqlParameter("#CmpyCode", SqlDbType.NVarChar)).Value = CV.Global.CMPYCODE;
sp.Add(new SqlParameter("#Code", SqlDbType.NVarChar)).Value = codeName;
sp.Add(new SqlParameter("#DisplayCode", SqlDbType.NVarChar)).Value = codeName + "-";
sp.Add(new SqlParameter("#TotalDigit", SqlDbType.Int)).Value = CV.Global.PARAMTOTALDIGIT;
insertData("<Sp Name>", sp);
My another function is insertData(...)
internal static int insertData(string spName, SqlParameterCollection sp)
{
int retObj = 0;
using (SqlConnection con = new SqlConnection(CV.Global.CONSTRING))
{
try
{
con.Open();
SqlCommand cmd = new SqlCommand(spName, con);
cmd.CommandType = CommandType.StoredProcedure;
if (sp.Count > 0)
{
foreach (SqlParameter param in sp)
cmd.Parameters.Add(param);
}
retObj = cmd.ExecuteNonQuery();
}
catch (Exception ev)
{
Util.Log(ev);
throw;
}
finally
{
try
{
con.Close();
}
catch (Exception ev) { Util.Log(ev); throw; }
}
}
return retObj;
}
I am trying to create a SqlParameterCollection and passed it to the insertData function. But it throws an error while I am calling sp.Add() method in my first function.
The error is
Object reference not set to an instance of an object
You cannot use any variable like SqlParameterCollection (a reference object) without a call to its constructor (new), but the SqlParameterCollection is an object that cannot be initialized directly with a new. It has no public constructor and can be retrieved only from the property of an existant SqlCommand.
SqlCommand cmd = new SqlCommand(commandText, connection);
SqlParameterCollection sp = cmd.Parameters;
I suggest to change your InsertData method to accept a List<SqlParameter> and let it handle the adding of the parameters to the SqlCommand that executes the command text
List<SqlParameter> sp = new List<SqlParameter>()
{
new SqlParameter() {ParameterName = "#CmpyCode", SqlDbType = SqlDbType.NVarChar, Value= CV.Global.CMPYCODE},
new SqlParameter() {ParameterName = "#Code", SqlDbType = SqlDbType.NVarChar, Value = codeName},
new SqlParameter() {ParameterName = "#DisplayCode", SqlDbType = SqlDbType.NVarChar, Value = codeName + "-"},
new SqlParameter() {ParameterName = "#TotalDigit", SqlDbType = SqlDbType.Int, Value = CV.Global.PARAMTOTALDIGIT}
};
insertData(CV.Sps.SP_INSERT_PARAM_TABLE, sp);
and insertData simply receives an optional list of SqlParameter and add them to the internal SqlCommand parameter collection if needed
internal static int insertData(string spName, List<SqlParameter> sp = null)
{
....
if(sp != null)
cmd.Parameters.AddRange(sp.ToArray());
....
}
Here is a simplified answer. I use this type of thing for a dynamic SQL query with dynamic parameters. Sometimes you don't need all parameters if you are writing a dynamic sqlquery when determining if a variable has a value.
List<SqlParameter> paramList = new List<SqlParameter>();
paramList.Add(new SqlParameter("#StartDate", StartDate));
paramList.Add(new SqlParameter("#EndDate", EndDate));
if (TicketID != "" && TicketID != null && TicketID != "undefined")
{
paramList.Add(new SqlParameter("#TicketID", TicketID));
SQLQuery = SQLQuery + " AND A.TicketID = #TicketID";
}
var Parameters = paramList.ToArray();
List<Report> ReportList = db.Database.SqlQuery<Report>(SQLQuery, Parameters).ToList();

Passing stored procedure parameters in c# .net application

I have a stored procedure and I am connecting it to my project and I wanted to know how I can pass the different parameter types in:
Stored procedure:
[dbo].[UploadAssignment]
#studentId int
, #guid uniqueidentifier
, #originalfilename nvarchar(500)
, #uploaddate datetime
In my project:
public virtual IEnumerable<T> GetUploadStudentSubmission<T>(int studentId, .."How should i format the remaining parameters")
{
SqlCommand _command = new SqlCommand("dbo.UploadAssignment");
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.Add(new SqlParameter { ParameterName = "studentId",SqlDbType = SqlDbType.Int, Value = sectionId});
_command.Parameters.Add(new SqlParameter { ParameterName = "guid", SqlDbType = SqlDbType.Int, Value = guid });
_command.Parameters.Add(new SqlParameter { ParameterName = "originalfilename", SqlDbType = SqlDbType.Int, Value = originalfilename });
_command.Parameters.Add(new SqlParameter { ParameterName = "uploaddate", SqlDbType = SqlDbType.Int, Value = uploaddate });
}
The official documentation states:
The ParameterName is specified in the form #paramname.
So you need to include the # in the parameter name. Other than that, you just need to pass in the relevant parameters just as you would to any other function, like this:
public virtual IEnumerable<T> GetUploadStudentSubmission<T>(
int studentId, Guid guid, string originalfilename, DateTime uploaddate)
{
SqlCommand _command = new SqlCommand("dbo.UploadAssignment");
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.Add(new SqlParameter { ParameterName = "#studentId",SqlDbType = SqlDbType.Int, Value = sectionId});
_command.Parameters.Add(new SqlParameter { ParameterName = "#guid", SqlDbType = SqlDbType.UniqueIdentifier, Value = guid });
_command.Parameters.Add(new SqlParameter { ParameterName = "#originalfilename", SqlDbType = SqlDbType.NVarChar, Value = originalfilename });
_command.Parameters.Add(new SqlParameter { ParameterName = "#uploaddate", SqlDbType = SqlDbType.DateTime, Value = uploaddate });
}
public virtual IEnumerable<T> GetUploadStudentSubmission<T>(int studentId, Guid guid, string originalfilename, DateTime uploaddate)
{
SqlCommand _command = new SqlCommand("dbo.UploadAssignment");
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.AddWithValue("#studentId",sectionId);
_command.Parameters.AddWithValue("#guid", guid );
_command.Parameters.AddWithValue("#originalfilename", originalfilename);
_command.Parameters.AddWithValue("#uploaddate", uploaddate);
}
Microsoft also provides the great Enterprise Library which beside other things contains a DataAccess block and handles parameters.
See this answer for more details https://stackoverflow.com/a/3038469/69433
You can also use the following code:
public virtual IEnumerable<T> GetUploadStudentSubmission<T>(int studentId, Guid guid, string originalfilename, DateTime uploaddate)
{
var command = Database.GetStoredProcCommand("[dbo].[UploadAssignment]");
Database.AddInParameter(command, "studentId", DbType.Int32, studentId);
Database.AddInParameter(command, "guid", DbType.Guid, guid);
Database.AddInParameter(command, "originalfilename", DbType.String, originalfilename);
Database.AddInParameter(command, "uploaddate", DbType.DateTime, uploaddate);
var reader = Database.ExecuteReader(command);
commandText = command.CommandAsSql();
reader.Close();
}

Adding more number of parameters to sqlparameter class

I have to call a stored procedure but i am having more number of parameters is there any simple way to do this? or simply adding every parameter to sqlparameter class?? like below
SqlCommand command = new SqlCommand("inserting", con);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#Firstname", SqlDbType.NVarChar).Value = TextBox1.Text;
Be aware that Paramters.Add has an overload that takes in a string and a DbType, so you don't have to call the Parameter constructor. You could replace the line you are currently using to add a new parameter:
command.Parameters.Add(new SqlParameter("#Firstname", SqlDbType.NVarChar)).Value = TextBox1.Text;
with the following shorter (but functionally equivalent) line:
command.Parameters.Add("#Firstname", SqlDbType.NVarChar).Value = TextBox1.Text;
If you want to add more parameters, you would simply add them to the Parameters property of your command, like so:
SqlCommand command = new SqlCommand("inserting", con);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#Firstname", SqlDbType.NVarChar).Value = TextBox1.Text;
command.Parameters.Add("#Lastname", SqlDbType.NVarChar).Value = TextBox2.Text;
Aside from that, have you tried using Parameters.AddWithValue? You can use this if the data type of your column maps to the type of your value in C#. You can find a mapping of C# to SQL Server data typse here.
You would use it like so:
// Assume your sproc has a parameter named #Age that is a SqlInt32 type
int age = 5;
// Since age is a C# int (Int32), AddWithValue will automatically set
// the DbType of our new paramter to SqlInt32.
command.Parameters.AddWithValue("#Age", 5);
If you need to specify the SqlDbType, AddWithValue returns the parameter you just added, so it's as simple as adding an extra statement to set the DbType property at the end, although at this point, you're better off just using the original .Add function and setting the value.
command.Parameters.AddWithValue("#Firstname", TextBox1.Text).DbType = SqlDbType.NVarChar;
Use Array of type SqlParameter and insert that into SqlCommand
SqlCommand Comm = new SqlCommand("Command text", new SqlConnection("Connection String");
SqlParameter[] param = {new SqlParameter("#Name","Value"),
new SqlParameter("#Name","Value"),
........
};
Comm.Parameters.AddRange(param);
Just call the command.Parameters.Add method multiple times:
SqlCommand command = new SqlCommand("inserting", con);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#Firstname", SqlDbType.NVarChar, 100).Value = TextBox1.Text;
command.Parameters.Add("#Lastname", SqlDbType.NVarChar, 100).Value = TextBox2.Text;
command.Parameters.Add("#City", SqlDbType.NVarChar, 100).Value = TextBox3.Text;
command.Parameters.Add("#ID", SqlDbType.Int).Value = Convert.ToInt32(TextBox4.Text);
....... and so on .....
You may use like it
return new SqlParameter[]
{
new SqlParameter("#Firstname", SqlDbType.VarChar)
{
Value = Firstname.Text
},
new SqlParameter("#Lastname", SqlDbType.VarChar)
{
Value = Lastname.Text
},
};
You can use dapper-dot-net
sample code:
var dog = connection.Query<Dog>("select Age = #Age, Id = #Id", new { Age = (int?)null, Id = guid });
Insert example:
connection.Execute(#"insert MyTable(colA, colB) values (#a, #b)",
new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
).IsEqualTo(3); // 3 rows inserted: "1,1", "2,2" and "3,3"
The command.Parameters.Add is deprecated. Rather use command.Parameters.AddWithValue .
For this, you would call it many times for each parameter.
// Mention size of the nvarchar column , here i give 500 , you can use its length for #Firstname as you mention in database according to your database
SqlCommand command = new SqlCommand("inserting", con);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#Firstname", SqlDbType.NVarChar,500).Value = TextBox1.Text;

Categories

Resources