C# dynamic query builder with SQL variables configurable - c#

Am developing a Prototype where in i can access the SQL server dynamically.Table names and column names should be configurable at run time.
Eg: If am selecting a table or inserting records i should pass those values to a Prototype Class with table name,column name and parameters. and the class should take care of the rest.
Am trying to build that class.
Advice on the recommended steps to start.
Thanks

DECLARE #ColName nvarchar(4000)
DECLARE #TableName nvarchar(4000)
DECLARE #ColName2 nvarchar(4000)
DECLARE #Parameter nvarchar(4000)
set #TableName='tblTest'
set #ColName='ID'
set #ColName2='colValue'
set #Parameter=1
DECLARE #sql nvarchar(4000)
SET #sql = ' SELECT '+#ColName+' from ' + #TableName+ ' where '+#ColName2+'='+#Parameter
exec(#sql)
this is what i am doing. you can pass the above given parameters to a stored procedure and that will do a trick

Maybe That is Useful ...
//Method
public void insertCheque()
{
try {
SqlParameter[] param = new SqlParameter[5];
param[0] = new SqlParameter("#IdBankChequeBook", SqlDbType.Int);
param[1] = new SqlParameter("#IdBankChequeType", SqlDbType.Int);
param[2] = new SqlParameter("#IdBankChequeStatus", SqlDbType.Int);
param[3] = new SqlParameter("#TransType",SqlDbType.Int);
param[4] = new SqlParameter("#ClientID",SqlDbType.Int);
//send sql parameter to stored procedure
SqlHelper.ExecuteNonQuery(Connecting.LCM, CommandType.StoredProcedure, "InsertBankCheque",param);
}
catch (Exception ex)
{
}
}
//Stored Procedure Related
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[InsertBankCheque]
#IdBankChequeBook int ,
#IdBankChequeType int ,
#IdBankChequeStatus int ,
#TransType int ,
#ClientID int ,
As
Insert into BankCheque
(
IdBankChequeBook,
IdBankChequeType,
IdBankChequeStatus,
TransType ,
ClientID )
values
(
#IdBankChequeBook,
#IdBankChequeType,
#IdBankChequeStatus,
#TransType,
#ClientID )

Related

How to Get IDENT_CURRENT result with c# ' s SqlCommand?

I have a stored procedure in which I want to get the last inserted row for a specific table say table TbUsers , so in the end of it, I type that line:
select IDENT_CURRENT('TbUsers')
Now I want to get that result in C#, using SqlCommand; I pass these parameters to to the stored procedure:
SqlCommand command = new SqlCommand("InsertUsers", conn);
command.CommandType = System.Data.CommandType.StoredProcedure;
/* Insert in TbUsager */
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("#firstName" ,value.firstname),
new SqlParameter("#lastName",value.lastname),
new SqlParameter("#email",value.email),
new SqlParameter("#phoneNumber",value.phoneNumber),
new SqlParameter("#address",value.address),
new SqlParameter("#country",value.country),
new SqlParameter("#city",value.city),
new SqlParameter("#zipCode",value.zip_code)
};
command.Parameters.AddRange(parameters);
var rdr = command.ExecuteReader()
How can I get the returned result of the stored procedure?
Update
i have added this code :
// command.Parameters.AddRange(parameters);
var LastInsertedUsagerId = new SqlParameter("#lastInsertedUsagerId", System.Data.SqlDbType.Int);
LastInsertedUsagerId.Direction = ParameterDirection.Output;
command.Parameters.Add(LastInsertedUsagerId);
// var rdr = command.ExecuteReader();
var LastInsertedUsagerId2 = command.Parameters["#LastInsertedUsagerId"].Value;
but i still getting null as a result ?
Update2
this is my SP:
ALTER PROCEDURE [dbo].[InsertUsager]
-- Add the parameters for the stored procedure here
#Nom_Usager varchar(20),
#Prenom_Usager varchar(20),
#Email_Usager varchar(20),
#Telephone_Portable_Usager varchar(20),
#Adresse_Usager varchar(20),
#Pays_Usager varchar(20),
#Ville_Usager varchar(20),
#IdVille_Usager varchar(20),
#LastInserted_IdUsager int OUTPUT
AS
BEGIN
-- Insert a new usager
declare #IdinsertedUsager table(IdinsertedUsager int)
declare #IdAddressVillePayselse table(IdAddressVillePayselse int)
declare #newUsager int , #IdAddressVillePays int , #addressvp int,#IdCountry int,#IdVille int
Insert into TbUsager (IdTypeUsager,Nom_Usager,Prenom_Usager,Indic_Maj)
Output inserted.IdUsager into #IdinsertedUsager
values(1,#Prenom_Usager,#Nom_Usager,'P')
SELECT #newUsager = IdinsertedUsager FROM #IdinsertedUsager
/* some code */
select #LastInserted_IdUsager=IDENT_CURRENT('TbUsers')
END
and it works well when i execute it in sqlserver
Assuming you're returning the identity id correctly(as output parameter) in your SP, in your C# code you can retrieve it like this:
var id = command.Parameters["#id"].Value;
Change #id to the name of your output variable in SP.
Here's a link to see how to do it correctly in detail:
https://www.aspsnippets.com/Articles/Return-Identity-value-from-Stored-Procedure-in-SQL-Server.aspx
Solved, in addition to #Siavash is answer , in order to work we need to use : command.ExecuteNonQuery()
instead of command.ExecuteReader()
In this documentation we get the difference and when to use each one.

How to read Scope Identity in C# from executed Stored Procedure

I want to read Scope_Identity via output variable '#RoleID' from where I am assigning value of scope identity.
C#:
private static long createNewRoleInsert(ADB.Model.RolesModel roleModelObj, MSSQL sql)
{
bool killConnection = Utils.getConnection(ref sql);
long returnValue = 0;
try
{
sql.SetSProc("[dbo].[p_Role_dfn_createNew]");
sql.AddParam("#Title", roleModelObj.Title);
sql.AddParam("#Description", roleModelObj.Description);
sql.AddParam("#CreatedDate", roleModelObj.CreatedDate);
var RoleID = sql.ExecuteNonQuery();
if(RoleID!=0 && RoleID>0)
{
returnValue = RoleID;
}
}
finally
{
if (killConnection)
sql.Dispose();
}
return returnValue;
}
Stored procedure:
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[p_Role_dfn_createNew]
#Title nvarchar(250),
#Description nvarchar(MAX) = NULL,
#CreatedDate DateTime,
#RoleID bigInt OUTPUT
AS
SET NOCOUNT ON;
SET XACT_ABORT ON
DECLARE #l_object AS SYSNAME = OBJECT_NAME(##PROCID),
#l_error_msg AS NVARCHAR(2000)
BEGIN TRY
BEGIN TRAN
INSERT INTO [adb_TestDb].[dbo].[Role] ([Title], [Description], [CreatedDate])
VALUES (#Title, #Description, #CreatedDate)
COMMIT TRAN
SET #RoleID = SCOPE_IDENTITY();
RETURN #RoleID
END TRY
BEGIN CATCH
-- rollback any open/uncomitted transactions
IF XACT_STATE() IN ( -1, 1) ROLLBACK TRANSACTION
-- return an error containing the object, error number and error description
SELECT #l_error_msg = 'Error number : ' + CAST(ERROR_NUMBER()AS VARCHAR) + '. ' + ERROR_MESSAGE()
RAISERROR (#l_error_msg,16,1)
END CATCH
The ExecuteNonQuery method doesn't return the return value from the procedure, it returns the number of rows affected.
To get the return value you would add a parameter with ParameterDirection.ReturnValue, however that won't safely get you the value in #RoleID as the return value from a procedure can't be a bigint, it's always an int.
As you already have #RoleID as an output parameter you should add parameter to the command to get the value. Example:
SqlParameter roleIdParam = new SqlParameter("#RoleID", SqlDbType.BigInt);
roleIdParam.Direction = ParameterDirection.Output;
cmd.Parameters.Add(roleIdParam);
// execute command
long roleId = (long)roleIdParam.Value;
You need to add an output parameter in C# to get the value of #RoleID from the stored procedure. Here's an example of that:
using System.Data.SqlClient;
using (SqlConnection conn = new SqlConnection("connectionString"))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "dbo.p_Role_dfn_createNew";
// add other parameters...
cmd.Parameters.Add(new SqlParameter("#RoleID", SqlDbType.BigInt))
.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
returnValue = (long)cmd.Parameters["#RoleID"].Value;
}
Change the
RETURN #RoleID
to
SELECT #RoleID
or add the output parameter as explained in other answers

Error calling SQL Server stored procedure from C# code

I have a stored procedure to create table in a SQL Server database. I need to call this stored procedure from C#. I get an exception
Incorrect Syntax near #TABLENAME
How do I fix this? I have the table name and column list from a xml file.
Stored procedure:
CREATE PROCEDURE PROC_CREATE_SFCOM_TABLE2
#TABLENAME VARCHAR(4000) ,
#COLUMNLIST VARCHAR(4000) ,
#ERRORMSG VARCHAR(4000) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #EXEC_IMMEDIATE_VAR VARCHAR (4000)
SELECT #EXEC_IMMEDIATE_VAR = 'CREATE TABLE #TABLENAME#COLUMNLIST '
EXECUTE (#EXEC_IMMEDIATE_VAR)
END
GO
C# Code:
using (SqlConnection conn = new SqlConnection(connstring)
{
using (SqlCommand cmd = new SqlCommand("dbo.PROC_CREATE_SFCOM_TABLE2",conn))
{
cmd.CommandType = CommandType.StoredProcedure;
createScript = "("+columnScript+")";
if (tableTableSpace != null)
{
if (tableTableSpace != "" || tableTableSpace != string.Empty)
{
createScript += "TABLESPACE " + tableTableSpace;
}
}
SqlParameter parameter = new SqlParameter("#TableName",SqlDbType.NVarChar);
parameter.Direction = ParameterDirection.Input;
parameter.Value = tableName;
cmd.Parameters.Add(parameter);
SqlParameter parameter2 = new SqlParameter("#COLUMNLIST",SqlDbType.NVarChar);
parameter2.Direction = ParameterDirection.Input;
parameter2.Value = createScript;
cmd.Parameters.Add(parameter2);
SqlParameter parameter3 = new SqlParameter("#ErrorMsg", SqlDbType.NVarChar);
parameter3.Direction = ParameterDirection.Output;
parameter3.Size = 4000;
cmd.Parameters.Add(parameter3);
conn.Open();
cmd.ExecuteNonQuery();
string errorMsg = parameter3.Value.ToString();
if (errorMsg != string.Empty)
LogInfo("Error: " + errorMsg);
You can't parameterize your table or column names. You can only parameterize your values. Only way is to execute dynamic sql.
But you should have a very strong validation for that if you want to create a table dynamic. Create a white list for that for example.
Before you do that, read: The Curse and Blessings of Dynamic SQL
You didn't create the dynamic SQL string correctly. Change it to this...
CREATE PROCEDURE PROC_CREATE_SFCOM_TABLE2
#TABLENAME VARCHAR(4000) ,
#COLUMNLIST VARCHAR(4000) ,
#ERRORMSG VARCHAR(4000) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #EXEC_IMMEDIATE_VAR VARCHAR (4000)
SELECT #EXEC_IMMEDIATE_VAR = 'CREATE TABLE [' + #TABLENAME + '] ' + #COLUMNLIST
EXECUTE (#EXEC_IMMEDIATE_VAR)
END
GO
However, please note that this is a very dangerous thing to do. #COLUMNLIST could contain anything, including other SQL commands, which could be used for a SQL injection attack

Entity Framework: how do I run a stored procedure and return a value?

Is it possible to execute a stored procedure using the Entity Framework, passing in variables and returning data along with a return value?
Please do not leave any code about function mappings with Entity Framework.
I have tried this and I keep getting the same damn error:
Procedure or function 'usp_BusinessUser_Search' expects parameter
'#TotalRecords', which was not supplied.
Here's my code:
SqlParameter Business = new SqlParameter("Business", Search.Term);
SqlParameter Location = new SqlParameter("Location", Search.Location);
SqlParameter PageNumber = new SqlParameter("PageNumber", Search.CurrentPage);
SqlParameter RecordsPerPage = new SqlParameter("RecordsPerPage", Search.RecordsPerPage);
SqlParameter TotalRecords = new SqlParameter("TotalRecords", 0);
SqlParameter parm = new SqlParameter()
{
ParameterName = "#TotalRecords",
Value = 0,
SqlDbType = SqlDbType.Int,
Direction = System.Data.ParameterDirection.Output
};
var List = db.ExecuteStoreQuery<ENT_SearchBusinessResult>("exec usp_BusinessUser_Search",Business,Location,PageNumber,RecordsPerPage,parm);
Does anyone have any idea what is causing this?
Thanks
EDIT:
Stored procedure code:
ALTER PROCEDURE [dbo].[usp_BusinessUser_Search] ( #Business nVarChar(255) = NULL
, #Location nVarChar(255) = NULL
, #PageNumber Int = 1
, #RecordsPerPage Int = 10
, #TotalRecords Int OUTPUT)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX)
, #CacheTable SYSNAME
, #TotalRows Int
, #Category VarChar(255)
, #BusinessCategory Int
, #TownCounty VarChar(50)
, #PcodeTownCounty VarChar(50)
INSERT Voucher_SearchHistory (Keyword, Location)
SELECT NULLIF(#Business,''), NULLIF(#Location,'')
This might help:
http://blogs.msdn.com/b/diego/archive/2012/01/10/how-to-execute-stored-procedures-sqlquery-in-the-dbcontext-api.aspx
You are not passing TotalRecords Sql Parameter in Excecute
var List = db.ExecuteStoreQuery<ENT_SearchBusinessResult>(
"exec usp_BusinessUser_Search",Business,
Location,PageNumber,RecordsPerPage,parm);
You can now use the following extension method, ExecuteSqlCommandWithReturn, that takes care of all of the work for you!
https://gist.github.com/copernicus365/7037320
string sql = "EXEC sp_CoolProc #SomeParam, #AnotherParam";
int returnValue;
int val = db.ExecuteSqlCommandWithReturn(sql, out returnValue, someParam, anotherParam);
The key to the solution was by Jieyang Hu here, which is this (though note that all of the following is fully handled by the aforementioned extension method): Just as you can do in a SQL prompt, you just set the result of the executed procedure to a SQL variable (in this case which is sent in as a parameter), like this:
EXEC #ReturnVal = sp_MyCoolProc;
This code adds the fragment #ReturnVal = after the first EXEC (followed by whitespace) it finds, and adds to the SqlParameters (or creates SqlParamters if there were none) a ReturnVal parameter, though the caller will never see these.
The parameter name should not contain #:
SqlParameter parm = new SqlParameter()
{
ParameterName = "TotalRecords",
Value = 0,
SqlDbType = SqlDbType.Int,
Direction = System.Data.ParameterDirection.Output
};
If you just added that parameter ('#TotalRecords) recently
I am going to guess that you just need to update your function import definition in your edmx model.

Ado.net ExecuteScalar() returning null

I am executing a stored procedure in c# (through vs2008) using ado.net with an ExecuteScalar command. The stored proc returns the pkey of the new record entered, but ExecuteScalar is returning null. I look in the database and a record has indeed been added. I could use an output parameter to get the value, but then I won't know why this didn't work.
When I execute the sp in ssms, the pkey is returned.
What am I doing wrong?
Here is the C# code:
public int SaveNewPerson(EPerson ePerson)
{
int newPersonPkey;
SqlConnection cn = new SqlConnection(cnn.PersonData);
using (cn)
{
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "People.dbo.AddNewPerson";
cmd.Parameters.Add("#LastName", SqlDbType.VarChar, 150).Value = ePerson.LastName;
cmd.Parameters.Add("#FirstName", SqlDbType.VarChar, 150).Value = ePerson.FirstName;
cn.Open();
object result = cmd.ExecuteScalar();
newPersonPkey = int.Parse(result.ToString());
cn.Close();
}
catch (Exception e)
{
// call error method
throw new Exception(e.Message + " save new Person error ");
}
}
return newPersonPkey;
}
And this is the sp:
PROCEDURE [dbo].[AddNewPerson]
#FirstName varchar(50)
,#LastName varchar(50)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [People].[dbo].[Persons]
(
[FirstName]
,[LastName]
)
VALUES
(
#FirstName
,#LastName
)
declare #persons_PKey int
set #persons_PKey = ##IDENTITY
return #persons_PKey
end
The ExecuteScalar method returns the first field of the first record of the result, but as your query doesn't produce a result, it will return null.
You can either select the value instead of returning it from the stored procedure, or add a parameter with the direction set to ParameterDirection.ReturnValue to catch what the stored procedure returns.
Try changing the Stored Procedure to use a Select Statement to return the identity instead of using a return like this:
SELECT CAST(scope_identity() AS int)
Thus changing your procedure to:
PROCEDURE [dbo].[AddNewPerson]
#FirstName varchar(50)
,#LastName varchar(50)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [People].[dbo].[Persons]
(
[FirstName]
,[LastName]
)
VALUES
(
#FirstName
,#LastName
)
SELECT CAST(scope_identity() AS int)
end
From the documentation of the ExecuteScalar() on MSDN it says that it will return the first column of the first row in the result set or null otherwise if the result set is empty.

Categories