Using output parameters when calling stored procedures with AsyncPoco - c#

I'm executing a SQL Server stored procedure which returns a single output parameter using AsyncPoco:
CREATE PROCEDURE [dbo].[GenerateId]
(#RETVAL VARCHAR(12) OUTPUT)
AS
DECLARE #pkgID VARCHAR(12)
BEGIN
SELECT #pkgID = 'ABC' + '000'
SELECT #RETVAL = #pkgID
END
GO
Here's how I'm calling it:
var spOutput = new SqlParameter("#RETVAL", System.Data.SqlDbType.VarChar)
{
Direction = System.Data.ParameterDirection.Output,
Size = 12,
};
var sql = $";EXEC [dbo].[GenerateId] #0 OUTPUT";
var response = await _dbAdapter.FetchAsync<dynamic>(sql, new object[] { spOutput });
return (string)spOutput.Value;
This is the error I get:
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Object.GetType()
at AsyncPoco.Database.FormatCommand(String sql, Object[] args) in C:\Aldenteware\AsyncPoco\code\AsyncPoco\Database.cs:line 2279

I figured it out:
var spOutput = new SqlParameter("#RETVAL", System.Data.SqlDbType.VarChar)
{
Direction = System.Data.ParameterDirection.Output,
Size = 12,
};
var sql = $";EXEC [dbo].[GenerateId] ##RETVAL = #0 OUTPUT";
var sqlClass = new Sql();
var s = sqlClass.Append(sql, spOutput);
var response = await _dbAdapter.ExecuteAsync(s);
return (string)spOutput.Value;

Related

How can i call OUT parameter in PROCEDURE via Npgsql

How can i call OUT parameter in PROCEDURE via Npgsql
I am getting this error when i run below code
-- PostgreSQL 14 -> PROCEDURE
CREATE OR REPLACE PROCEDURE sp_add_users_new(arrJsnUsers JSON[], jOut OUT JSON) AS $$
DECLARE
intSpStatus INT;
v json;
BEGIN
FOREACH v IN ARRAY arrJsnUsers
LOOP
INSERT INTO tbl_user (vhr_name, vhr_password, sin_record_status)
VALUES(v->>'strName', v->>'strPassword', (v->>'intRecordStatus')::SMALLINT);
END LOOP;
COMMIT;
intSpStatus = 1;
jOut['intSpStatus'] = intSpStatus;
END;
$$ LANGUAGE plpgsql
--Dot net core 5
using (NpgsqlConnection objCon = new NpgsqlConnection("..."))
{
objCon.Open();
using (NpgsqlCommand objSqlCommand = new NpgsqlCommand("CALL sp_add_users_new(:p1, :p2)", objCon))
{
// Parameters
NpgsqlParameter[] lstSqlParameter = {
new NpgsqlParameter("p1", NpgsqlDbType.Array|NpgsqlDbType.Json) {
Value = lstUsers,
DataTypeName = "arrJsnUsers"
},
new NpgsqlParameter("p2", NpgsqlDbType.Json) {
Value = jOut,
DataTypeName = "jOut",
Direction = ParameterDirection.Output
},
};
objSqlCommand.Parameters.AddRange(lstSqlParameter);
// Execute
IDataReader objDataReader = objSqlCommand.ExecuteReader();
}
objCon.Close();
}
--Error
42703: column "p2" does not exist
Below is a sample which works - it's recommended to read the Npgsql docs on this. Some comments:
You don't specify the output parameter in SQL - just pass a NULL as per the PostgreSQL docs.
Since #p2 is an output parameter, it makes no sense to specify its value (jOut1 above).
DataTypeName (jOut above) also doesn't make sense here; that's used to indicate to Npgsql which PG type to send for input parameters (similar to NpgsqlDbType).
using var objCon = new NpgsqlConnection("Host=localhost;Username=test;Password=test");
objCon.Open();
using var objSqlCommand = new NpgsqlCommand("CALL sp_add_users_new(#p1, NULL)", objCon);
// Parameters
var lstUsers = new[] { #"{ ""Foo"": ""Bar"" }" };
NpgsqlParameter[] lstSqlParameter = {
new NpgsqlParameter("p1", NpgsqlDbType.Array|NpgsqlDbType.Json) { Value = lstUsers, DataTypeName = "arrJsnUsers"},
new NpgsqlParameter("p2", NpgsqlDbType.Json) { Direction = ParameterDirection.Output},
};
objSqlCommand.Parameters.AddRange(lstSqlParameter);
// Execute
IDataReader objDataReader = objSqlCommand.ExecuteReader();
Console.WriteLine(objSqlCommand.Parameters[1].Value);

Can't handle if reader.ReadDataTable() doesn't return any DATA from stored procedure in database

I have created an API called GetCustomerPrivacyStatus, it is trying to find out the TandCstatus.
[HttpGet]
[Route("GetCustomerPrivacyStatus")]
public async Task<EULAInfo> GetCustomerPrivacyStatus()
{
var result = new EULAInfo();
string userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var orgId = await GetOrgIdOfUser().ConfigureAwait(false);
var TandCvalue = MasterDatabase.GetTermsAndConditionstatus(orgId).ToString();
var TandCInt = TandCvalue != null ? TandCvalue : "0";
var TandCstatus = Int16.Parse(TandCInt) == 0 ? false : true;
result.status = TandCstatus;
return result;
}
In the GetTermsAndConditionstatus it is calling a stored procedure, if the orgId is new that means it is not present is the database, that's why dataTable.Rows[0]["TermsAndConditionAccepted"] is throwing an error
There is no row at position 0
I am not able to able to think how to resolve this situation.
public object GetTermsAndConditionstatus(string orgId)
{
using (var reader = new StoredProcedureReader(this, "GetTermsAndConditionstatus", new { orgId }))
{
var dataTable = reader.ReadDataTable();
var result = dataTable.Rows[0]["TermsAndConditionAccepted"] ;
return result;
}
}
Stored procedure is:
CREATE PROCEDURE [dbo].[GetTermsAndConditionstatus]
#orgId VARCHAR(100)
AS
SELECT TermsAndConditionAccepted
FROM TermsAndConditionCheck
WHERE OrgId = #orgId
Is there is any way if there is no rows the result variable should be set to null?
object result = null;
using (var reader = new StoredProcedureReader(this, "GetTermsAndConditionstatus", new { orgId }))
{
var dataTable = reader.ReadDataTable();
if (dataTable.Rows.Count > 0)
result = dataTable.Rows[0]["TermsAndConditionAccepted"];
}
return result;
That should fix your problem

Count line in SQL query

I try to count line in my SQL query.
It works without parameter. For example, if I assign directly FIOForm = 'SmithJJ'. I really don't understand what I'm doing wrong.
Exception: the SqlParameter is already contained by another SqlParameterCollection
int kolNar = 0;
System.Data.SqlClient.SqlParameter Name = new System.Data.SqlClient.SqlParameter("#Name", System.Environment.UserName);
var pushStat = db.Database.SqlQuery<Reestr>("select * from Reestr where FIOForm = #Name and Status = 'Executed'", Name);
foreach (var u in pushStat)
{
kolNar = pushStat.Count();
}
if (kolNar > 0)
MessageBox.Show(kolNar.ToString());
I suppose you can call:
Dispose();
before
System.Data.SqlClient.SqlParameter Name = new System.Data.SqlClient.SqlParameter("#Name", System.Environment.UserName);

How to query multiple result in specify value in dapper

I want return all records when data.Task = 0 in this query. how to do it?
var data = SqlConn.ConnectSQL().Query("Select TicketNo, PickName From TaxiTicket Where DriverID = #ID AND Status = #State",
new { ID = find.Account, State = data.Task });
var data = SqlConn.ConnectSQL().Query("Select TicketNo, PickName From TaxiTicket
Where DriverID = #ID AND (Status = case #State when 0 then Status else #state end)",
new { ID = find.Account, State = data.Task });
this only addresses your point of question, how you prepare and pass parameters is another issue. you seem to have some weird assignment using same data variable.

SqlBuilder returning wrong result

I have a query using Npgsql and Postgres. For building my query I am using Dapper and its SqlBuilder.
When I make the normal statement in the DB it is returning the correct result. When I am doing it via the SqlBuilder it is returning the wrong result.
I tried different way, changed the addTemplate or the parameters, but it changed nothing.
Also I have tried to change the line builder.Where("period = #period", new { model.Period }); in different ways:
builder.Where("period = #Period", new { model.Period });
builder.Where("period = period", new { model.Period });
builder.Where("period = #TestPeriod", new { TestPeriod = model.Period });
Or is this a more common way:
builder.Where("period = '" + model.Period + "'");
using (NpgsqlConnection con = Helper.GetNpgsqlConnection())
{
var builder = new SqlBuilder();
var selector = builder.AddTemplate("SELECT * FROM szzRecord.folders /**where**/");
if (model.Period != null)
builder.Where("period = #period", new { model.Period });
var result = con.Query(selector.RawSql);
return result;
}
The result with the normal sql query for example: SELECT * FROM szzRecord.folders WHERE period = 24 is returning 251 rows - which is correct.
The result with the dapper query is 1223, which are all rows. So it kinda looks that the parameter doesn't exist. On expecting the selector I find my parameter for period. I found Period = 24 inselector.parameters.templates[0]. Is this correct? selector.parameters.parameters is empty.
You need to pass the SqlBuilder's parameters into your query. You have:
var result = con.Query(selector.RawSql);
Change this to:
var result = con.Query(selector.RawSql, selector.Parameters);

Categories