EF6 SqlQuery with named parameters - c#

I have a stored procedure accepting a few paramaters but I can't figure out the right syntax. According to varios sources, the following should work:
var results = base.Context.Database.SqlQuery<UserSummary>("exec FindPatients forenames = #forenames, surname = #surname",
new SqlParameter("#forenames", string.IsNullOrWhiteSpace(forenames) ? (object)DBNull.Value : forenames),
new SqlParameter("#surname", string.IsNullOrWhiteSpace(surname) ? (object)DBNull.Value : surname));
When .ToList() is called, I get an SqlException: Incorrect syntax near '='.
I've tried removing the exec:
var results = base.Context.Database.SqlQuery<UserSummary>("FindPatients #forenames, #surname",
new SqlParameter("#forenames", string.IsNullOrWhiteSpace(forenames) ? (object)DBNull.Value : forenames),
new SqlParameter("#surname", string.IsNullOrWhiteSpace(surname) ? (object)DBNull.Value : surname));
Which results in The SqlParameter is already contained by another SqlParameterCollection
I don't want to use numbered parameters and pass {1}, {2} etc in to the sproc as I need 10 or so parameters and it's a maintenance nightmare. Am I missing something?

Related

Passing and using a List<string> as Oracle Binding Parameter

I have a query ending with :
AND U2.USER_ID IN (:ToUserIDs)
My ToUserIDs is List<string> being created from entries in a TextBox.:
ToUserIDs = new List<string>(ToUserIDsTextBox.Text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries));
My OracleParameter is set up as follow:
OracleParameter oracleParameter3 = oracleDataAdapter.SelectCommand.Parameters.Add(":ToUserIDs", OracleDbType.NVarchar2);
oracleParameter3.Direction = ParameterDirection.Input;
oracleParameter3.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
oracleParameter3.Value = (List<string>)args["ToUserIDs"];
Here I am running into deep water as I am not sure who to handle Lists/Arrays in an OracleParameter.
I am getting this error:
Unable to cast object of type 'System.Collections.Generic.List`1[System.String]'
to type 'System.String[]
This wont work. The IN in clause only supports:
fixed length of scalars, like:
AND U2.USER_ID IN (:P1, :P2, :P3)
a subquery
AND U2.USER_ID IN (select x from y)
You can rewrite your query using TABLE cast keyword
AND U2.USER_ID IN (select * from TABLE(:P1))
Where P1 is parameter of type: array of varhar2
Used a post by #saminpa (Oracle Parameters with IN statement?) as solution.
AND U2.USER_ID IN (SELECT IDS.ToUserID FROM XMLTABLE('/ToUserIDs/ToUserID' PASSING XMLTYPE (:ToUserIDsElement) COLUMNS ToUserID VARCHAR(100) PATH '/ToUserID/.') IDS)

DbContext ExecuteSqlRaw missing parameters error

I have this code for executing stored procedure:
var result = await DbContext.Database.ExecuteSqlRawAsync(
"Get_FlightBooking #BookingReferenceNumber, #BM_BKDTFOM, #BM_BKDTTO, #User_Id",
new SqlParameter("#BookingReferenceNumber", model.BookingId == string.Empty ? null : model.BookingId),
new SqlParameter("#BM_BKDTFOM", model.FromDt == string.Empty ? null : model.FromDt),
new SqlParameter("#BM_BKDTTO", model.FromDt == string.Empty ? null : model.FromDt),
new SqlParameter("#User_Id", model.UserId));
This is the stored procedure:
ALTER Proc [dbo].[Get_FlightBooking]
(
#BookingReferenceNumber VARCHAR(50)=NULL,
#BM_BKDTFOM VARCHAR(50)=NULL,
#BM_BKDTTO VARCHAR(50)=NULL,
#User_Id bigint=null
)
as
begin
SELECT distinct BookingID,
BookingReferenceNumber,
Sector,
AirlineCode,
AirlineName,
FROM dbo.Flights AS fb
WHERE (fb.BookingReferenceNumber=#BookingReferenceNumber OR #BookingReferenceNumber IS NULL)
AND((CAST(fb.BookingDate AS DATE)>= CAST(#BM_BKDTFOM AS DATE) OR #BM_BKDTFOM IS NULL) AND (CAST(fb.BookingDate AS DATE)<=CAST(#BM_BKDTTO AS DATE) OR #BM_BKDTTO IS NULL))
AND (fb.UserId=#User_Id or #User_Id=1)
END
Is anyone seeing something wrong in the way how the stored procedure is being executed? When calling the C# code I'm getting this error:
The parameterized query '(#BookingReferenceNumber
nvarchar(4000),#BM_BKDTFOM nvarchar(400' expects the parameter
'#BookingReferenceNumber', which was not supplied.
Any idea what can be wrong?
You need to use DBNull.Value and not null
var result = await DbContext.Database.ExecuteSqlRawAsync(
"UspGet_FlightBooking #BookingReferenceNumber, #BM_BKDTFOM, #BM_BKDTTO, #User_Id",
new SqlParameter("#BookingReferenceNumber", string.IsNullOrWhiteSpace(model.BookingId) ? DNNull.Value : model.BookingId),
new SqlParameter("#BM_BKDTFOM", string.IsNullOrWhiteSpace(model.FromDt) ? DNNull.Value : model.FromDt),
new SqlParameter("#BM_BKDTTO", string.IsNullOrWhiteSpace(model.FromDt) ? DNNull.Value : model.FromDt),
new SqlParameter("#User_Id", model.UserId));
If you cant use C# 9.0 maybe try initialising your SqlParameters like this:
new SqlParameter("#BookingReferenceNumber", System.Data.SqlDbType.NVarChar, 4000)
{ Value = string.IsNullOrWhiteSpace(model.BookingId) ? (object)DBNull.Value : model.BookingId }

Build sql query with string builder and a lot of parameters

I am building my query using loops
for (var i = 0; i < query.BlackWhiteListFieldMatchProxy.Count; i++)
{
sb.Append($#"(
MatchType = {(int)query.BlackWhiteListFieldMatchProxy[i].MatchType}
AND EntityType = {(int)query.BlackWhiteListFieldMatchProxy[i].EntityType}
AND MatchFieldType = {(int)query.BlackWhiteListFieldMatchProxy[i].MatchFieldType}
AND (
(
MatchValue = '{query.BlackWhiteListFieldMatchProxy[i].MatchValue1}'
OR MatchValue = {query.BlackWhiteListFieldMatchProxy[i].MatchValue2Or ?? "Null"}
)
AND
(
{query.BlackWhiteListFieldMatchProxy[i].MatchValue2And ?? "Null"} is Null
OR MatchValue2 is Null
OR MatchValue2 = {query.BlackWhiteListFieldMatchProxy[i].MatchValue2And ?? "Null"}
)
)
)");
if (i != query.BlackWhiteListFieldMatchProxy.Count - 1)
sb.Append($#"
OR");
}
But I have the problem with this
{query.BlackWhiteListFieldMatchProxy[i].MatchValue2And ?? "Null"} is Null
If it Null It'll work, otherwise the real value will be without ""
The thing is I cant use something like
#MatchValue
Because I have the list of parameters with the same name which differs only by it's number in the List the names will be the same and It won't map it properly
for (var i = 0; i < query.BlackWhiteListFieldMatchProxy.Count; i++)
{
var match = query.BlackWhiteListFieldMatchProxy[i];
cmd.Parameters.AddWithValue($"#matchType{i}", (int)match.MatchType);
cmd.Parameters.AddWithValue($"#entityType{i}", (int)match.EntityType);
cmd.Parameters.AddWithValue($"#fieldType{i}", (int)match.MatchFieldType);
sb.Append($#"(
MatchType = #matchType{i}
AND EntityType = #entityType{i}
AND MatchFieldType = #fieldType{i}
... etc
Add additional parameters per required element - so there will be #matchType0, #matchType1, etc - then you have no injection vulnerabilities. One thing to watch: parameters with a value of null are not sent, so check for null and either generate different SQL, or be sure to set the parameter value to DBNull.Value in that case.
First of all this is terrible way of structuring SQL. This SQL has many issues. First and most important thing is it is open to SQL Injection Attacks. But, It has also other performance related issues where SQL Query is changing whenever different value is provided.
I Suggest you to use parameterized SQL. here is the most basic example for it.
Please note that code may be subject to change according to the library that you are going to use.
// 1. declare command object with parameter #City
SqlCommand cmd = new SqlCommand(
"select * from Customers where city = #City", conn);
// 2. define parameters used in command object
SqlParameter param = new SqlParameter();
param.ParameterName = "#City";
param.Value = inputCity;
if we turn back to your case. The Final Code would be like this:
"... SQL ...
MatchType = #matchType AND
... SQL ..."
The code needs to be like
cmd.Parameters.AddWithValue("#matchType", (int)match.MatchType);
and for the null values you may consider to use
DbNull.Value

How to pass the table name and the selected fields as parameters

I get the following error :
ERROR:-201
MEssage: [Informix .NET provider][Informix]A syntax error has occurred.
when I try to execute this code :
string table_name = resultDt.Rows[0][1].ToString();
string pdf_column = resultDt.Rows[0][0].ToString();
st.Append(" SELECT ? FROM ?");
paramList.Clear();
paramList.Add("#tablename", table_name);
paramList.Add("#pdf_column", pdf_column);
resultDt =dalHelper.Return_DataTable(st.ToString(), CommandType.Text, paramList);
return resultDt;
You can't.
Use String.Replace instead.
st.Append(" SELECT #pdf_column FROM #tablename");
st.Replace("#tablename", table_name);
st.Replace("#pdf_column", pdf_column);
If table_name and pdf_column comes from user input in anyway you should use a QuoteName function (i.e. QuoteName(table_name)) to prevent sql injection. Don't know about Informix but here is one for SqlServer.

sql query to avoid null value parameter

these are the variables i am passing to some method where i need to write some sql query like
string cmd = #"select *
from students_tbl
where
course_id=#courseId and branch_id=in(+" branchId "+)
and passout_year>=#passoutYear
and current_backlog>=#currentBacklog
and gender=#gender
and eGap<=#eGap
and first_year_percent>=#firstyearPercent
and second_year_percent>=#seconYearPercent
and third_year_percent>=#thirdyearPercent";
and so on but problem is that few of these parameters are optional means for those variable
there value is null so i don't want to include those parameter in query
so how should i eliminate those null variable i am not getting how should i write query to solve this issue
those parameter are random nothing fix when they will be null because hey are optional
so how should i write query by using only not null parameter
Just add an is null check before your comparison, which will short-circuit if the input parameter value is null, e.g.:
where (#currentBacklog is null or current_backlog >= #currentBacklog)
You can test for a null value in the condition, and use the value from the table instead. Example:
... where course_id = isnull(#courseId, course_id) ...
Instead of having
cmd = "one long string with many clauses, some of which are optional"
try
cmd = "first clause, required"
if second param is not null then
cmd = cmd & "second clause, optional"

Categories