I am getting a SqlException
Procedure or function 'GetDashboardData' expects parameter '#userID', which was not supplied.
I have been trying to follow this post, however does not seem to cater for passing parameters.
https://msdn.microsoft.com/en-us/data/jj691402.aspx and then looked for fixes
I have then continued to try and pass it a parameter but got this exception thrown (shown above) and googled around. I have tried the first answer post in this post as it seems the most relevant and quickest way
Passing parameter to Stored Procedure using DbContext
However this did not work so was wondering how do I go about passing this parameter?
string userID = User.Identity.GetUserId();
// If using code first we need to make sure the model built before we open a connection
db.Database.Initialize(force: false);
var command = db.Database.Connection.CreateCommand();
command.CommandText = "[dbo].[GetDashboardData]";
var userIDParameter = new SqlParameter { ParameterName = "#userID", Value = userID, DbType = DbType.String, Direction = ParameterDirection.Input };
command.Parameters.Add(userIDParameter);
try
{
db.Database.Connection.Open();
// We now run the stored procedure
var reader = command.ExecuteReader();
var getUserDashboards = ((IObjectContextAdapter)db).ObjectContext.Translate<DashboardModel>(reader, "DashboardModel", MergeOption.AppendOnly);
}
finally
{
db.Database.Connection.Close();
}
Related
My goal is to get a list of reports from my stored procedure, and return this list as JSON. I am using similar code to this elsewhere in my controller, the difference here is the stored procedure I wrote requires a parameter, and that is where the issue lies.
The error that is thrown is "System.Exception: 'Must declare the scalar variable "#DynamicCategoryId"" I have tried a few different ways to get the parameter to work, with no luck.
Here is my code:
[HttpGet]
[Route("GetReports/{categoryId}")]
public string GetReports(int categoryId)
{
List<GetReporsResult> paramaters = new List<GetReporsResult>();
try
{
SqlParameter paramCategoryId = new SqlParameter("#DynamicCategoryId", SqlDbType.Int);
paramCategoryId.SourceColumn = "#DynamicCategoryId";
paramCategoryId.Value = categoryId;
paramCategoryId.Direction = ParameterDirection.Input;
paramaters = context.GetReporsResult.FromSqlRaw("EXEC dbo.GetReports #DynamicCategoryId", paramCategoryId.Value).ToList();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return JsonConvert.SerializeObject(paramaters);
}
Interestingly, if I do ("EXEC dbo.GetReports " + categoryId.ToString() ) it works, however that is not a good practice.
Never use Parameter.Value as an parameter. Check category id , it could empty.
and try this code, it was used many times in many places
var paramCategoryId = new SqlParameter("#DynamicCategoryId", categoryId);
paramaters = context.GetReporsResult.FromSqlRaw("EXEC dbo.GetReports #DynamicCategoryId",
paramCategoryId).ToList();
or I am usually using
paramaters = context.GetReporsResult.FromSqlRaw("EXEC dbo.GetReports #DynamicCategoryId",
parameters: new[] { paramCategoryId} ).ToList();
I'm posting this for two reasons
I'm new to PostgreSQL and it took a while to piece this information together, so I thought someone else would find this helpful and
to ask if there is another way to call a PostgreSQL stored procedure that doesn't require all of the parameters to be included in the stored procedure name/signature.
The following uses Dapper and Npgsql to make a call to a PostgreSQL stored procedure that inserts (null id_inout passed in) or updates a record (id_inout has a value).
I'd like to understand why PostgreSQL requires the entire stored procedure signature when making the call.
public static int? PO_Save(PurchaseOrder po)
{
int? recordId = null;
using (var cn = new NpgsqlConnection(AppSettings.ConnectionString))
{
if (cn.State != ConnectionState.Open)
cn.Open();
var procName = "CALL po_save(#in_ponumber,#in_deliverydate,#in_bldnum," +
"#in_facname,#in_facnumber,#in_facaddress1,#in_facaddress2,#in_city," +
"#in_state,#in_zip,#in_theme,#id_inout)";
var p = new Dapper.DynamicParameters();
p.Add("#in_ponumber", po.PONumber);
p.Add("#in_deliverydate", po.DeliveryDate);
p.Add("#in_bldnum", po.BldNum);
p.Add("#in_facname", po.FacName);
p.Add("#in_facnumber", po.FacNumber);
p.Add("#in_facaddress1", po.FacAddress1);
p.Add("#in_facaddress2", po.FacAddress2);
p.Add("#in_city", po.City);
p.Add("#in_state", po.State);
p.Add("#in_zip", po.Zip);
p.Add("#in_theme", po.Theme);
p.Add("#id_out", po.POID, null, ParameterDirection.InputOutput);
var res = cn.Execute(procName, p);
recordId = p.Get<int>("#id_inout");
}
return recordId;
}
You should be able to pass commandType: CommandType.StoredProcedure to Execute, e.g:
var res = cn.Execute(
"po_save",
new {
in_ponumber = po.PONumber,
in_deliverydate = po.DeliveryDate,
// etc...
},
commandType: CommandType.StoredProcedure,
);
Here's the docs with such an example: https://github.com/StackExchange/Dapper/blob/main/Readme.md#stored-procedures
I wanted to find an answer to this myself, and beginning with Npgsql 7.0, CommandType.StoredProcedure will now invoke stored procedures and not functions as before.
I am trying to get output value from the dbcontext using the method FromSql(...).
If i execute it on SSMS, it works but not working in EF core.
My SP param:
#totalItems VARCHAR(MAX) OUTPUT
I've removed other params for readable and point out the issue. The records are coming but the OUTPUT parameter is always null.
Linq
IQeryable<T> = _context.Set<T>().FromSql("Sp_Todo #totalItems OUTPUT", // i also tried with OUT or without both Out/Output but no luck
new SqlParameter("#totalItems", SqlDbType.Varchar)
{ Direction = ParameterDirection.Output});
I don't' have access to your whole code, but nothing ever gets executed against your queryable source until you try to enumerate it. So, probably it didn't run the Stored Procedure when you tried to get the OUTPUT.
To force immediate query evaluation you can do it:
IQueryable<T> foo = _context.Set<T>().FromSql("Sp_Todo #totalItems OUTPUT", new SqlParameter("#totalItems", SqlDbType.Varchar) { Direction = ParameterDirection.Output });
//totalItems output still null
var bar = foo.ToList()
//totalItems output not null anymore
Here's how I'm doing it:
var _companyCode = new SqlParameter("CompanyCode", "HST");
var _sMsg = new SqlParameter("sMsg", "")
{
Direction = ParameterDirection.Output,
SqlDbType = SqlDbType.VarChar
};
var sql = "exec temp_get_company #CompanyCode, #sMsg OUTPUT";
var result = context.Set<Company>().FromSql(sql, _companyCode, _sMsg).ToList();
var yourOutput = _sMsg.Value.ToString();
Creating a web app, where data is being retrieved from a SQL Server stored procedure to a controller class in Web Api 2. I want to access the values of the resultset in the controller.
The result set will be sent back to model, using Angular uri.
Stored procedure:
CREATE PROCEDURE proc_ToBeInitiate(
#status varchar(50),
#retVal int output)
AS
BEGIN
select
INITIATED_FOR, [emp name],
INITIATED_by, REQUESTED_DATE,
UPLOADED_LOA, UPLOADED_Bg_Check_Form
from
tbl_User t , tbl_INITIATED I, tbl_SUBJECT_FORM S
where
t.[Emp No] = I.[INITIATED_FOR]
and S.[Emp No] = I.INITIATED_FOR
and i.PROGRESS_STATUS = #status
SET #retVal = 100 --It is to check whether I am getting correct Output value
END
GO
Procedure is returning the expected output.
Here is controller class method :
[HttpGet]
[ResponseType(typeof(ToBeIntiated))]
[Route("api/ToBeInitiated/{status}")]
public IHttpActionResult ToInitiated(string status)
{
var retVal = new SqlParameter() { ParameterName = "retVal", Direction = ParameterDirection.Output, SqlDbType = SqlDbType.Int };
var locstatus = new SqlParameter("status", SqlDbType.VarChar,255);
locstatus.Value = status;
using (var x = new DB_BgCheckEntities())
{
IEnumerable<ToBeIntiated> toBeInitiated = x.Database.SqlQuery<ToBeIntiated>
("proc_ToBeInitiate #status,#retVal out", locstatus, retVal).ToList<ToBeIntiated>();
foreach (WebApplication12.DTO.ToBeIntiated i in toBeInitiated)
{
Console.WriteLine(i.EmployeeID);
}
if ((int)retVal.Value == 10)
{
return Ok(toBeInitiated);
}
else{
return NotFound();
};
}
var toBeInitiated is not returning resultset, though in Sql Server, values are being populated.
Please help me in resolving the issue.
The null reference exception comes from the fact that retVal.Value is null and you are trying to cast it to an int primitive.
The reason is likely found in the following line:
var retVal = new SqlParameter() { ParameterName = "#val", Direction = ParameterDirection.Output, SqlDbType = SqlDbType.Int };
you are setting ParameterName to "#val", but in the sproc it's named "#retVal".
Change parameter name from #val to #retval in the following line
var retVal = new SqlParameter() { ParameterName = "#retval", Direction = ParameterDirection.Output, SqlDbType = SqlDbType.Int };
Declare #RetVal int
Declare #status varchar(50)
exec GetEmployees #status = #status out , #retVal =#RetVal out
Output parameters are set after resulting dataset(s) are read.
Please go through this, it may help you.
Edit:
You have to do something like below:
var idParam = new SqlParameter {
ParameterName = "id",
Value = 1};
var votesParam = new SqlParameter {
ParameterName = "voteCount",
Value = 0,
Direction = ParameterDirection.Output };
var results = context.Database.SqlQuery<Person>(
"GetPersonAndVoteCount #id, #voteCount out",
idParam,
votesParam);
var person = results.Single();//This line is important
var votes = (int)votesParam.Value;
I can not see
ok(resultsetobject)
in your code.
So, finally able to resolve my error.
Here are few things that friends here and I did, to resolve my error :
Using Exec proc_name #var1,var2 - I got to know that in VS2013 Exec is unnecessary, and might be it was one of the reasons for error :
the sqlparameter is already contained by another sqlparametercollection
Find the difference between dbcontext.Database.ExecuteCommand and dbcontext.Database.SqlQuery<Tentity>. Former is used for commands like, Create, Update, Delete, Insert, while later is for Select query.
Earlier I was using dbcontext.Database.ExecuteCommand();
ResultSets are of type IEnumerable, and when there is output parameter, iterate the resultset. For Ex:
foreach (WebApplication12.DTO.ToBeIntiated i in toBeInitiated)
Console.WriteLine(i.EmployeeID);
Then only, output parameter of stored procedure is available.
Add .ToList<Tentity>, if resultset variable is passed in your model, otherwise your resultset won't be converted into JSON data. Ex:
var resultSet = dbcontext.Database.SQlquery
("storedproc #a",a).ToList();
return Ok(resultSet); //Data in Json Format will be sent back to model
Also, TEntity property's name should be same as the column name, which stored procedure will return. This is mentioned SQLQuery definition.
Finally, my error, value of status passed in the stored procedure from was wrong.
Value is case-sensitive, which I found in my case.
PS : Thanks everyone for resolving my issue. Please feel free to correct my concepts.
Reference :
To retrieve the output parameter, resultset should be iterated.
Credit #Nilesh
I have inherited a function in an ASP.NET (C#) application where the author used the Microsoft.Practices.EnterpriseLibrary.Data library, but I have been asked to change it so that it uses System.Data.OracleClient. This function uses a stored procedure form a database. itemName, and openDate are string parameters that the function takes in. PKG_AUCTION_ITEMS.IsAuctionItem is the stored procedure function name.
Here is the code that I received:
string result = String.Empty;
Database db = DatabaseFactory.CreateDatabase("OraData");
using (DbCommand cmdDB = db.GetStoredProcCommand("PKG_AUCTION_ITEMS.IsAuctionItem"))
{
db.AddInParameter(cmdDB, "vItemName", DbType.String, itemName);
db.AddInParameter(cmdDB, "vOpenDate", DbType.String, openDate);
db.AddParameter(cmdDB, "ret", DbType.String, 2, ParameterDirection.ReturnValue, false, 0, 0, null, DataRowVersion.Current, null);
db.ExecuteNonQuery(cmdDB);
result = cmdDB.Parameters["ret"].Value.ToString();
}
Here is my code:(connstr is the connection string)
string result = String.Empty;
OracleConnection conn = new OracleConnection(connstr);
OracleCommand cmd = new OracleCommand("PKG_AUCTION_ITEMS.IsAuctionItem",conn);
myCmd.CommandType = CommandType.StoredProcedure;
using (myCmd)
{
myCmd.Parameters.AddWithValue("vItemName", itemName);
myCmd.Parameters.AddWithValue("vOpenDate", openDate);
myCmd.Parameters.AddWithValue("ret", ???);
myCmd.ExecuteNonQuery();
result = myCmd.Parameters["ret"].Value.ToString();
}
I do not understand what the difference between AddInParameter and AddParameter is, and what this line does:
db.AddParameter(cmdDB, "ret", DbType.String, 2, ParameterDirection.ReturnValue, false, 0, 0, null, DataRowVersion.Current, null);
Am I on the right track? Can anyone please help?
Thanks
db.AddParameter adds an output parameter in this case. You need to let the db client library know that you're looking to get the return value back from the sproc call. Hence the call to AddParameter. db.AddInParameter adds a parameter which is only an in-parameter. In the It's a shortcut for db.AddParameter using ParameterDirection.Input. See http://blogs.x2line.com/al/archive/2006/03/25/1579.aspx for a discussion of AddInParameter vs. AddParameter.
Similarly, using OracleClient, AddWithValue is like AddInParameter-- a shortcut to use for input params when you already know the value. Since the return value is, by definition, an output parameter, you can't use AddWithValue. You need to use Parameters.Add() instead.
Now, back to your main question: what's the equivalent code using OracleClient. It's something like this:
string result = String.Empty;
OracleConnection conn = new OracleConnection(connstr);
OracleCommand cmd = new OracleCommand("PKG_AUCTION_ITEMS.IsAuctionItem",conn);
myCmd.CommandType = CommandType.StoredProcedure;
using (myCmd)
{
myCmd.Parameters.AddWithValue("vItemName", itemName);
myCmd.Parameters.AddWithValue("vOpenDate", openDate);
// depending on whether you're using Microsoft's or Oracle's ODP, you
// may need to use OracleType.Varchar instead of OracleDbType.Varchar2.
// See http://forums.asp.net/t/1002097.aspx for more details.
OracleParameter retval = new OracleParameter("ret",OracleDbType.Varchar2,2);
retval.Direction = ParameterDirection.ReturnValue;
myCmd.Parameters.Add(retval);
myCmd.ExecuteNonQuery();
result = myCmd.Parameters["ret"].Value.ToString();
}
We actually do the configuration of the parameters more explicitly, something like this
System.Data.OracleClient.OracleCommand command = new System.Data.OracleClient.OracleCommand("PACKAGE_NAME.STORED_NAME");
command.CommandType = System.Data.CommandType.StoredProcedure;
System.Data.OracleClient.OracleParameter param;
param = new System.Data.OracleClient.OracleParameter("PARAM_NAME_ID", System.Data.OracleClient.OracleType.Number);
param.Value = id;
command.Parameters.Add(param);
param = new System.Data.OracleClient.OracleParameter("PARAM_NAME_RETURN_COUNT", System.Data.OracleClient.OracleType.Number);
param.Direction = System.Data.ParameterDirection.Output;
command.Parameters.Add(param);
...
You see, there is a property direction which we explicitly assign for the parameter that is being returned. The first gets the value of a variable "id" and is a parameter that gets passed TO the stored procedure.
The 2nd one is being returned by the stored procedure, therefore no value is assigned to that parameter value and the direction is set to "System.Data.ParameterDirection.Output"