Must declare the scalar variable "#ManagerID" - c#

I have a Running Time Error:
Must declare the scalar variable \"#ManagerID
I'm Sure I Have Declare All Variables In My CLass And My Procudure
My Class Code:
public DataTable Select(int ID,string NameFa, string Address, int ManagerID, short TotalUnits, int ChargeMethodID)
{
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
table.Columns.Add("NameFa", typeof(string));
table.Columns.Add("Address", typeof(string));
table.Columns.Add("ManagerID", typeof(int));
table.Columns.Add("TotalUnits", typeof(short));
table.Columns.Add("ChargeMethodID", typeof(int));
try
{
con.Open();
SqlCommand command = new SqlCommand("dbo.SelectBuilding", con);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#ID", ID));
command.Parameters.Add(new SqlParameter("#NameFa", NameFa));
command.Parameters.Add(new SqlParameter("#Address", Address));
command.Parameters.Add(new SqlParameter("#ManagerID", ManagerID));
command.Parameters.Add(new SqlParameter("#TotalUnits", TotalUnits));
command.Parameters.Add(new SqlParameter("#ChargeMethodID", ChargeMethodID));
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(table);
return table;
}
And My Procudure Code Is:
#ID int,
#NameFa nvarchar(150),
#Address nvarchar(MAX),
#ManagerID int,
#TotalUnits smallint,
#ChargeMethodID int
As
Begin
IF(#ID >0 )
Begin
Select ID,NameFa,Address,ManagerID,TotalUnits,ChargeMethodID From Buildings where ID = #ID
End
ELSE
Begin
Declare #sqlTxt nvarchar(MAX)
SET #sqlTxt = 'SELECT ID,NameFa,Address,ManagerID,TotalUnits,ChargeMethodID FROM Buildings where ID>0'
IF(#NameFa!= null)
BEGIN
SET #sqlTxt = #sqlTxt + ' AND NameFa Like ''%#NameFa%'''
END
IF(#Address!= null)
BEGIN
SET #sqlTxt = #sqlTxt + ' AND Address Like ''%#Address%'''
END
IF(#ManagerID > 0)
BEGIN
SET #sqlTxt = #sqlTxt + ' AND ManagerID = #ManagerID'
END
IF(#TotalUnits > 0)
BEGIN
SET #sqlTxt = #sqlTxt + ' AND TotalUnits = #TotalUnits'
END
IF(#ChargeMethodID > 0)
BEGIN
SET #sqlTxt = #sqlTxt + ' AND ChargeMethodID = #ChargeMethodID'
END
EXEC (#sqlTxt);
End
END
And I want to use Select Function:
DataTable dt = new DataTable();
Buildings.Building bb = new Buildings.Building() {ID=0,NameFa="",Address="",ManagerID=OwnerID,TotalUnits=0,ChargeMethodID=0 };
dt = bu.Select(bb.ID,bb.NameFa,bb.Address,bb.ManagerID,bb.TotalUnits,bb.ChargeMethodID);

You are not passing the parameters to the exec statement. I would change it to sp_executesql which has an optional argument with parameters.
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql
Edit: I strongly suggest getting rid of the exec and/or sp_executesql commands. Because depending on the input you could:
a) Get runtime errors due to user typing SQL string delimiters as a valid input. Example O'Hara as a surname.
b) A malicious user could mess badly with your database.
You could get similar result in a more simple way:
Select
ID,NameFa,Address,ManagerID,TotalUnits,ChargeMethodID
From
Buildings
where
(#Id = 0 or ID = #Id)
and (#NameFa = '' or NameFa = #NameFa)
and (#ManagerID = 0 or ManagerID = #ManagerID)
// repeat for the rest of the optional search conditions

Related

Date Format: No overload for method "ToString" takes 1 arguments

I stay with that error when I'm trying to format a date in my code:
Cmd.CommandText = #"
DECLARE #command varchar(5000);
DECLARE #RestoreList TABLE(DB_name VARCHAR(100), RS_name VARCHAR(100), RS_DateFinExercice DATE, RS_IsClosed VARCHAR(50));
SELECT #command = 'IF ''?'' IN (SELECT name FROM sys.databases WHERE HAS_DBACCESS(name) = 1 AND CASE WHEN state_desc = ''ONLINE'' THEN OBJECT_ID( QUOTENAME( name ) + ''.[dbo].[P_DOSSIER]'',''U'' ) END IS NOT NULL) BEGIN USE [?] SELECT DB_name = CAST(DB_NAME() AS VARCHAR(100)), RS_name = CAST(a.D_RaisonSoc AS VARCHAR(100)), RS_DateFinExercice = CAST((SELECT Max(v) FROM (VALUES (a.[D_FinExo01]), (a.[D_FinExo02]), (a.[D_FinExo03]),(a.[D_FinExo04]),(a.[D_FinExo05])) AS value(v)) AS DATE), RS_IsClosed = CAST((SELECT CASE WHEN (SUM (CASE WHEN JM_Cloture !=2 THEN 1 ELSE 0 END)>0) THEN '''' ELSE ''arc'' END FROM F_JMOUV) AS VARCHAR(50)) FROM [dbo].[P_DOSSIER] a INNER JOIN F_JMOUV b ON DB_name() = DB_NAME() GROUP BY D_RaisonSoc, D_FinExo01, D_FinExo02, D_FinExo03, D_FinExo04, D_FinExo05 HAVING COUNT(*) > 1 END'
INSERT INTO #RestoreList EXEC sp_MSforeachdb #command;
SELECT * FROM #RestoreList ORDER BY DB_name;";
SqlDataReader dr = Cmd.ExecuteReader();
List<DBtoRestore> dgUIDcollection = new List<DBtoRestore>();
if (dr.HasRows)
{
while (dr.Read())
{
DBtoRestore currentdgUID = new DBtoRestore
{
CUID_dbname = dr["DB_name"].ToString(),
CUID_RaisonSoc = dr["RS_name"].ToString(),
CUID_DateFinExercice = dr["RS_DateFinExercice"].ToString(),
CUID_IsClosed = dr["RS_IsClosed"].ToString()
};
dgUIDcollection.Add(currentdgUID);
}
}
dgDBtoRestore.ItemsSource = dgUIDcollection;
Cnx.Close();
The problem is on this line of code:
CUID_DateFinExercice = dr["RS_DateFinExercice"].ToString()
For now, my datagrid report date like 01/01/2020 00:00:00. In SQL, I have 01-01-2020 style.
I want to have the same style in my datagrid.
I have try something like ToString("dd-MM-yyyy") but it's in that context I've received the error.
Any idea to help me?
Convert to a DateTime and then call ToString on it:
Convert.ToDateTime(dr["RS_DateFinExercice"]).ToString("dd-MM-yyyy")
Solution :
CUID_DateFinExercice = ((DateTime)dr["RS_DateFinExercice"]).ToString("dd-MM-yyyy"),

Calling stored procedure error on return value error data type nvarchar(max) to int

I calling a stored procedure and it has an int return value. However there is an error on returning the value back to my back end.
public async Task<string> CreatePortfolio(Portfolio portfolio)
{
string statusMessage;
using (SqlConnection conn = new SqlConnection(Connection))
{
SqlParameter returnValue = new SqlParameter(); //Holds the bit that determines if insert was successful or not
SqlCommand command;
command = new SqlCommand();
command.Connection = conn;
conn.Open();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "USP_Add_Portfolio";
command.Parameters.AddWithValue("#portfolioName", portfolio.PortfolioName);
command.Parameters.AddWithValue("#description", portfolio.Description);
command.Parameters.AddWithValue("#createID", portfolio.CreateID);
command.Parameters.AddWithValue("#updateID", portfolio.UpdateID);
command.Parameters.AddWithValue("#statusMessage", SqlDbType.NVarChar).Direction = ParameterDirection.Output;
returnValue.Direction = ParameterDirection.ReturnValue;
command.Parameters.Add(returnValue);
int i = await command.ExecuteNonQueryAsync().ConfigureAwait(false);
if(i == 1)
{
statusMessage = command.Parameters["#statusMessage"].Value.ToString();
}
else
{
statusMessage = "Error while adding please contact your administrator";
}
}
return statusMessage;
}
This is the stored procedure:
create procedure USP_Add_Portfolio
(#portfolioName as nchar(30) = null,
#description as nvarchar(200) = null,
#createID as nvarchar(40) = null,
#updateID as nvarchar(40) = null,
#statusMessage as nvarchar(max) output)
as
declare #success as int = 0
if #portfolioName is null
raiserror('Stored procedure USP_Add_Portfolio - Missing Parameter #portfolioName', 16,1)
else if exists( select * from Portfolio where [Portfolio_Name] = #portfolioName COLLATE SQL_Latin1_General_CP1_CI_AS)
begin
set #statusMessage = rtrim(#portfolioName) + ' already exists please try another portfolio name'
raiserror('Stored procedure USP_Add_Portfolio - Already exists #portfolioName', 16,1)
return 0
end
else if #createID is null
raiserror('Stored procedure USP_Add_Portfolio - Missing Parameter #Create_ID', 16,1)
else if #updateID is null
raiserror('Stored procedure USP_Add_Portfolio - Missing Parameter #Update_ID', 16,1)
else
begin
insert into Portfolio ([Portfolio_Name], [Long_Description], [Create_ID], [Create_TS], [Update_ID], [Update_TS])
values (#portfolioName, #description, #createID, getdate(), #updateID, getdate())
--Check to see if insert worked
set #statusMessage = case when ##ROWCOUNT = 1 then 'Successfully added ' + #portfolioName else 'Unable to add please try again' end
set #success = case when ##ROWCOUNT = 1 then 1 else 0 end
end
return #success
go
The stored procedure finishes and it adds the new record but it errors on
int i = await command.ExecuteNonQueryAsync().ConfigureAwait(false);
Error:
expecting an int but gets nvarchar
ExecuteNonQuery (not worrying about the async for the moment...) returns the number of rows affected for UPDATE, INSERT, DELETE, and -1 otherwise. It does NOT return information directly from the stored procedure.
In your case above, I think you should call the "await" without the "int i =" and not worry about the return value from the ExecuteNonQueryAsync call. Instead, after the value, look at the value in returnValue.Value, which would be the value of the "return" parameter. It is an object, so verify the type or use Convert.ToInt32().
This doesn't look correct because SqlDbType.NVarChar is an enumeration value:
command.Parameters.AddWithValue("#statusMessage", SqlDbType.NVarChar).Direction = ParameterDirection.Output;
What happens if you use this instead:
command.Parameters.Add(new SqlParameter("#statusMessage", SqlDbType.NVarChar, -1)).Direction = ParameterDirection.Output;

ASP.NET MVC C# - No mapping exists from object type System.String[] to a known managed provider native type

I'm having a problem in my code. Can someone help me.
When running the line "comm.ExecuteScalar();", I received an error message.
Error Message says "No mapping exists from object type System.String[] to a known managed provider native type."
My stored proc is attached.
Code:
using (SqlConnection conn = new SqlConnection(System.Convert.ToString(database.DbConnect("database1"))))
{
var procedure = "sp_auth_sign_in";
int result = 0;
try
{
conn.Open();
using (SqlCommand comm = new SqlCommand(procedure, conn))
{
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.AddWithValue("#employeeid", model.EmployeeId);
comm.Parameters.AddWithValue("#password", model.Password);
comm.Parameters.Add("#emp_name", SqlDbType.VarChar, 50).Direction = ParameterDirection.Output;
comm.Parameters.Add("#role_group", SqlDbType.VarChar, 2).Direction = ParameterDirection.Output;
comm.Parameters.Add("#chg_pass", SqlDbType.Bit).Direction = ParameterDirection.Output;
comm.Parameters.Add("#img_path", SqlDbType.VarChar, 1000).Direction = ParameterDirection.Output;
comm.Parameters.Add("#division_group", SqlDbType.VarChar, 3).Direction = ParameterDirection.Output;
comm.Parameters.Add("#department_group", SqlDbType.VarChar, 3).Direction = ParameterDirection.Output;
comm.Parameters.Add("#firstname", SqlDbType.VarChar, 25).Direction = ParameterDirection.Output;
comm.Parameters.Add("#logintries", SqlDbType.Int).Direction = ParameterDirection.Output;
comm.Parameters.Add("#uname_docutrack", SqlDbType.VarChar, 50).Direction = ParameterDirection.Output;
comm.Parameters.Add("#ustatus_docutrack", SqlDbType.Bit).Direction = ParameterDirection.Output;
comm.Parameters.Add("#SignatoryInitial", SqlDbType.VarChar, 3).Direction = ParameterDirection.Output;
comm.Parameters.Add("#result", SqlDbType.Int).Direction = ParameterDirection.Output;
comm.ExecuteScalar(); // got an error here.
Code for sp_auth_sign_in procedure:
CREATE procedure [dbo].[sp_auth_sign_in]
#employeeid varchar(25)='', /* username for contractors; employee id for */
#password varchar(25)='',
#emp_name varchar(50) output,
#role_group varchar(2) output,
#chg_pass bit output,
#img_path varchar(100) output,
#division_group varchar(3) output,
#department_group varchar(3) output,
#firstname varchar(25) output,
#logintries int output,
#uname_docutrack varchar(50) output,
#ustatus_docutrack bit output,
#SignatoryInitial varchar(3) output,
#result int output
as
/*****************************
Date : June 17, 2015
*****************************/
/* variable(s) */
declare
#statvar bit=0,
#stat_tries tinyint=0,
#passcode int=0
set #logintries = 0
/* trim white space(s) */
set #employeeid=dbo.fn_lrtrim(#employeeid)
set #password=dbo.fn_lrtrim(#password)
/* raise error for null entries or any */
if(#employeeid='')
begin
set #result=1
return 1
end
if(#password='')
begin
set #result=2
return 2
end
/* check if username/employee id is valid. */
if not exists
(
select
aum.employeeid
from dbo.app_users_megaworld aum with (nolock)
where aum.employeeid=#employeeid
)
begin
set #result=3
return 3
end
/* check if account is active */
select
#statvar=aur.active
from dbo.app_users_roles aur with (nolock)
where aur.employeeid=#employeeid
if(#statvar=0)
begin
set #result=4
return 4
end
/* count login attempts */
select
#stat_tries=aur.tries
from dbo.app_users_roles aur with (nolock)
where aur.employeeid=#employeeid
if(#stat_tries>=5)
begin
/* deactivate account if tries>=3 */
exec dbo.sp_app_users_active #employeeid, 0
/* reset login attempt in effect for the account deactivation */
exec dbo.sp_app_users_tries #employeeid, 0
set #result=5
return 5
end
/* check username and password combination */
exec dbo.sp_crt_user_passcode #employeeid, #password, #passcode output
if not exists
(
select
aur.passcode
from dbo.app_users_roles aur with (nolock)
where aur.employeeid=#employeeid and aur.passcode=#passcode
)
begin
/* increase counter for login attempt(s) */
exec dbo.sp_app_users_tries #employeeid, 1
select #logintries = tries from app_users_roles where employeeid = #employeeid
set #result=6
return 6
end
/* account is valid */
/* reset counter for login attempt(s) */
exec dbo.sp_app_users_tries #employeeid, 0
/* raise flag for signing-in */
exec dbo.sp_app_users_logon #employeeid, 1 -- <-- change to 1 in production
/* output user's information */
select
--#emp_name=rtrim(upper(aum.firstname) + ' ' + upper(aum.lastname) + ' ' + upper(iif(aum.suffix='', '', aum.suffix))) ,
#emp_name=rtrim(aum.firstname + ' ' + aum.lastname + ' ' + iif(aum.suffix='', '', aum.suffix)) ,
#role_group=aur.role_group,
#chg_pass=aur.chg_pass,
#img_path=iif(aum.img_path is null or aum.img_path='','/Images/Avatar/avatar.jpg', aum.img_path),
#division_group=aum.division_group,
#department_group=aum.department_group,
#firstname=upper(aum.firstname),
#uname_docutrack = isnull(aud.username,''),
#ustatus_docutrack = isnull(aud.accountstatus,0),
#SignatoryInitial = isnull(aum.SignatureInitial, '')
from dbo.app_users_megaworld aum with (nolock)
inner join dbo.app_users_roles aur with (nolock)
on aum.employeeid=aur.employeeid
full join dbo.app_user_roles_docutrack aud
on aum.employeeid = aud.employeeid and aud.systemtype = 'MyTracking'
where aum.employeeid=#employeeid
set #result=0
return 0
GO
Update:
The problem is here:
comm.Parameters.AddWithValue("#employeeid", model.EmployeeId);
comm.Parameters.AddWithValue("#password", model.Password);
-In my storedproc, the datatype of employeeId is varchar but in my Model view it is set as "dynamic".
-I really don't know what's happening here since i'm just a newbie but when I changed it to "string", it works well.
-Remaining issue is when I'm setting a session.
Error here:
Session["EmployeeID"] = model.EmployeeId.Replace(",", "").ToUpper;
Error 2 Cannot convert method group 'ToUpper' to non-delegate type 'object'. Did you intend to invoke the method?
namespace WMSPortal.Models
{
public class LoginViewModel
{
public string EmployeeId { get; set; }
//public dynamic EmployeeId { get; set; }

Building dynamic sql query with between and order by key word

I have a situation where parameter to my sql query would be dynamic.if parameter is null i don't want to add it to the query,I have tried some thing(never worked)..and it look like stoopid to me now
ds = SqlHelper.ExecuteDataset(GlobalSettings.DbDSN, CommandType.Text, "SELECT TOP 1000 [ID],[Project],[Owner],[Consultant],[Contractor],[Value],[Level1],[Level2] ,[Status] ,[Category] ,[Country],[CreatedDate],[CreatedByID],[CreatedByName] FROM [tbl_Projects] where"+if(!string.IsNullOrEmpty(paraCategory)){ "[Category] = #Category and"}+"+ Country =#country and "+if(!string.IsNullOrEmpty(paraCategory)){ " value between #val1 and #val2"}+" order by CreatedDate asc",
new SqlParameter("#Category", paraCategory),
new SqlParameter("#Country", paraCountry),
new SqlParameter("#val1", paraValue1),
new SqlParameter("#val2", paraValue2));
I have checked Building dynamic sql also
here
But it is not usefull where I need to put like and between key words..can any one give me a hand on this?
Just to give you an idea, I would do something like this:
var sql as new StringBuilder();
sql.Append("SELECT ... all your columns ... FROM yourTable");
var parameters as new List(Of SqlParameter);
if (!string.IsNullOrEmpty(paraCategory)
{
sql.Append("[Category]=#Category,");
parameters.AddWithvalue("#Category", paraCategory);
}
sql.Length -= 1
//...your other parameters...
sql.Append("ORDER BY CreatedDate");
And then pass it all to your SqlHelper:
ds = SqlHelper.ExecuteDataset(GlobalSettings.DbDSN, CommandType.Text, sql.ToString(), parameters);
Also note that the above code is not really defensive. So for example if no parameter is delivered it will fail. And since I don't know the SqlHelper-Class, you might need to have something else than a List(Of SqlParameter).
Change SqlHelper.ExecuteDatasetso that it takes a delegate to call the specific code you want:
class SqlHelper
{
public delegate void SqlCommandDelegate(SqlCommand command);
public Dataset ExecuteDataset(string dsn,
CommandType commandType,
SqlCommandDelegate specificPreparations)
{
Dataset results;
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = dsn;
using (SqlCommand command = conn.CreateCommand())
{
command.CommandType = commandType;
connection.Open();
specificPreparations(command);
SqlDataReader reader = command.ExecuteReader();
results.Load(reader);
}
}
return results;
}
}
Then to call it:
ds = SqlHelper.ExecuteDataset(GlobalSettings.DbDSN,
CommandType.Text,
delegate(SqlCommand command)
{
command.CommandText = "SELECT BLAH FROM BLAH";
foreach (var myParameter in myParameterList)
{
SqlParameter p = new SqlParameter();
// Construct p
command.Paramters.Add(p)
}
// Anything else you want to do to the command
});
}
you can do this using a SP
CREATE PROCEDURE MyDynamicSP(#Condition1 as varchar(100),Condition2 as varchar(100),Condition3 as varchar(100))
AS
SET NOCOUNT ON
DECLARE #STRSQL VARCHAR(1000)
SET #STRSQL = 'SELECT * FROM MyTable WHERE '
IF NOT #Condition1 IS NULL
#STRSQL = #STRSQL + ' ' + #Condition1
IF NOT #Condition2 IS NULL
#STRSQL = #STRSQL + ' ' + #Condition2
IF NOT #Condition3 IS NULL
#STRSQL = #STRSQL + ' ' + #Condition3
EXEC sp_executesql #STRSQL
SET NOCOUNT OFF
You can do the testing inside the query as such :
SELECT *whatever you need*
FROM [tbl_Projects]
where
(#Category is null or [Category] = #Category) and
(#Country is null or [Country] = #country) and
(#val1 is null or value > #val1) and
(#val2 is null or value < #val2)
order by CreatedDate asc
And you always send the 4 parameters. On the plus side, you can build your query in a SQL worksheet and it's easier to spot syntax errors an so on.
You might need to add some tests for what would be an empty value, though.

Pass table valued parameter using ADO.NET

How to pass table valued parameter to stored procedure using ADO.NET?
Create type in SQL Server:
CREATE TYPE [dbo].[MyDataType] As Table
(
ID INT,
Name NVARCHAR(50)
)
Create Procedure:
CREATE PROCEDURE [dbo].[MyProcedure]
(
#myData As [dbo].[MyDataType] Readonly
)
AS
BEGIN
SELECT * FROM #myData
END
Create DataTable in C#:
DataTable myDataTable = new DataTable("MyDataType");
myDataTable.Columns.Add("Name", typeof(string));
myDataTable.Columns.Add("Id", typeof(Int32));
myDataTable.Rows.Add("XYZ", 1);
myDataTable.Rows.Add("ABC", 2);
Create SQL Parameter:
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "#myData";
parameter.SqlDbType = System.Data.SqlDbType.Structured;
parameter.Value = myDataTable;
command.Parameters.Add(parameter);
I tried this and received the exception:
The table type parameter '#MyDataType' must have a valid type name.
I had to set the "TypeName" property of the SqlParameter:
parameter.TypeName = "MyDataType";
This question is a duplicate of How to pass table value parameters to stored procedure from .net code. Please see that question for an example illustrating the use of either a DataTable or an IEnumerable<SqlDataRecord>.
For multilinguals, a little late to the show:
a) elsewhere on tsql
--- create a vector data type
CREATE TYPE [dbo].[ItemList] AS TABLE([Item] [varchar](255) NULL)
b)
Dim Invoices As New DataTable("dbo.ItemList") 'table name is irrelevant
Invoices.Columns.Add("Invoice", GetType(String))
...
With .SqlCommand.Parameters
.Clear()
.Add(New Data.SqlClient.SqlParameter() With {
.SqlDbType = Data.SqlDbType.Structured,
.Direction = Data.ParameterDirection.Input,
.ParameterName = "#Invoices",
.TypeName = "dbo.ItemList",
.Value = Invoices})
End With
...
' using store procedure
.CommandText = "SELECT * FROM dbo.rpt(#invoices) "
' or direct reference is a select
.CommandText = "SELECT * FROM dbo.invoicedata" +
"where ((select count(*) from #invoices) = 0 or "+
"InvoiceNumber in (select distinct * from #Invoices))
You can prefix with Exec
using( SqlConnection con = new SqlConnection( "Server=.;database=employee;user=sa;password=12345" ) )
{
SqlCommand cmd = new SqlCommand( " exec ('drop table '+#tab)" , con );
cmd.Parameters.AddWithValue( "#tab" ,"Employee" );
con.Open( );
cmd.ExecuteNonQuery( );
}

Categories