In order to prevent SQLinjection. I need to change my code from simple String
to OracleParameter
. Also I need to bypass LINQ because of its limitation in my WHERE CLAUSE as you can see below and last for better performance. By the way this code is working before I use OracleParameter
.
I got this error message "Value does not fall within the expected range".
What's wrong or missing on my code, specially on OracleParameter
and ExecuteStoreQuery
part?
I'm using the following:
Code(.cs)
public List<ProgramAssetCodeViewModel> GetAssetToList(long _channelID, DateTime _startDate, DateTime _endDate, DateTime _startTime, DateTime _endTime, string _programName, bool isActualAiring)
{
List<ProgramAssetCodeViewModel> assetList = new List<ProgramAssetCodeViewModel>();
try
{
string qry = @"SELECT D.CHANNEL_NAME CHANNEL_NAME, TO_DATE(TO_CHAR(FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', B.PROG_AIR_DT),'MM/DD/YYYY'),'MM/DD/YYYY') AIRING_DT, A.PROG_NAME, C.PROG_BODY_ASSET_CD, FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001' || TO_CHAR(B.START_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) START_TIME, FN_TR_CONVERT_UTC_TIME ('TO_LOCAL',TO_DATE('01/01/2001' || TO_CHAR( B.END_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) END_TIME, ASCII(UPPER(SUBSTR(C.PROG_BODY_ASSET_CD, -1)))-64 PROG_BODY_NO FROM PROGRAM_MSTR A, PROG_SKED_DTL B, PROG_BODY_MSTR C, CHANNEL_MSTR D WHERE B.CHANNEL_ID = D.CHANNEL_ID AND A.PROGRAM_ID = B.PROGRAM_ID AND B.PROG_SKED_ID = C.PROG_SKED_ID(+) AND B.CHANNEL_ID = :CHANNEL_ID AND A.PROG_NAME LIKE ('%' || :PROG_NAME ||'%') AND A.PROG_NAME NOT LIKE 'BS%' AND A.PROG_NAME NOT LIKE 'B/S%' AND (TO_DATE(TO_CHAR(FN_TR_CONVERT_UTC_TIME('TO_LOCAL', B.PROG_AIR_DT),'MM/DD/YYYY'),'MM/DD/YYYY') >= TO_DATE(:START_DATE,'MM/DD/YYYY') AND FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001' || TO_CHAR(B.START_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) >= TO_DATE ('01/01/2001 ' || :START_TIME, 'MM/DD/YYYY HH24:MI')) AND (TO_DATE(TO_CHAR(FN_TR_CONVERT_UTC_TIME('TO_LOCAL', B.PROG_AIR_DT),'MM/DD/YYYY'),'MM/DD/YYYY') <= TO_DATE(:END_DATE,'MM/DD/YYYY') AND ((TO_DATE ('01/01/2001 ' || :START_TIME, 'MM/DD/YYYY HH24:MI') < TO_DATE ('01/01/2001 ' || :END_TIME, 'MM/DD/YYYY HH24:MI') AND FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001' || TO_CHAR( B.END_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) <= TO_DATE ('01/01/2001 ' || :END_TIME, 'MM/DD/YYYY HH24:MI')) OR (TO_DATE ('01/01/2001 ' || :START_TIME, 'MM/DD/YYYY HH24:MI') >= TO_DATE ('01/01/2001 ' || :END_TIME, 'MM/DD/YYYY HH24:MI') AND FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001' || TO_CHAR( B.END_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) <= TO_DATE ('01/02/2001 ' || :END_TIME, 'MM/DD/YYYY HH24:MI')))) ORDER BY CHANNEL_NAME, AIRING_DT, START_TIME, END_TIME, PROG_BODY_NO";
string qryActual = @"SELECT D.CHANNEL_NAME CHANNEL_NAME, TO_DATE(TO_CHAR(FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', B.PROG_AIR_DT),'MM/DD/YYYY'),'MM/DD/YYYY') AIRING_DT, A.PROG_NAME, C.PROG_BODY_ASSET_CD, FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001' || TO_CHAR(B2.ACTUAL_START_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) START_TIME, FN_TR_CONVERT_UTC_TIME ('TO_LOCAL',TO_DATE('01/01/2001' || TO_CHAR( B2.ACTUAL_END_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) END_TIME, ASCII(UPPER(SUBSTR(C.PROG_BODY_ASSET_CD, -1)))-64 PROG_BODY_NO FROM PROGRAM_MSTR A, PROG_SKED_DTL B, PROG_SKED_ACTUAL B2, PROG_BODY_MSTR C, CHANNEL_MSTR D WHERE B.CHANNEL_ID = D.CHANNEL_ID AND B.CHANNEL_ID = B2.CHANNEL_ID(+) AND B.PROGRAM_ID = B2.PROGRAM_ID(+) AND B.START_DT = B2.START_DT(+) AND B.START_TIME = B2.START_TIME(+) AND B.PROG_AIR_DT = B2.PROG_AIR_DT(+) AND A.PROGRAM_ID = B.PROGRAM_ID AND B.PROG_SKED_ID = C.PROG_SKED_ID(+) AND B.CHANNEL_ID = :CHANNEL_ID AND (TO_DATE(TO_CHAR(FN_TR_CONVERT_UTC_TIME('TO_LOCAL', B.PROG_AIR_DT),'MM/DD/YYYY'),'MM/DD/YYYY') >= TO_DATE(:START_DATE,'MM/DD/YYYY') AND FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001' || TO_CHAR(B2.ACTUAL_START_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) >= TO_DATE ('01/01/2001 ' || :START_TIME, 'MM/DD/YYYY HH24:MI')) AND (TO_DATE(TO_CHAR(FN_TR_CONVERT_UTC_TIME('TO_LOCAL', B.PROG_AIR_DT),'MM/DD/YYYY'),'MM/DD/YYYY') <= TO_DATE(:END_DATE,'MM/DD/YYYY') AND ((TO_DATE ('01/01/2001 ' || :ACTUAL_START_TIME, 'MM/DD/YYYY HH24:MI') < TO_DATE ('01/01/2001 ' || :ACTUAL_END_TIME, 'MM/DD/YYYY HH24:MI') AND FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001' || TO_CHAR( B2.ACTUAL_END_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) <= TO_DATE ('01/01/2001 ' || :END_TIME, 'MM/DD/YYYY HH24:MI')) OR (TO_DATE ('01/01/2001 ' || :ACTUAL_START_TIME, 'MM/DD/YYYY HH24:MI') >= TO_DATE ('01/01/2001 ' || :ACTUAL_END_TIME, 'MM/DD/YYYY HH24:MI') AND FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001' || TO_CHAR( B2.ACTUAL_END_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) <= TO_DATE ('01/02/2001 ' || :END_TIME, 'MM/DD/YYYY HH24:MI')))) AND A.PROG_NAME LIKE ('%' || :PROG_NAME ||'%') AND A.PROG_NAME NOT LIKE 'BS%' AND A.PROG_NAME NOT LIKE 'B/S%' ORDER BY CHANNEL_NAME, AIRING_DT, START_TIME, END_TIME, PROG_BODY_NO";
StringBuilder sb = isActualAiring ? sb = new StringBuilder(qryActual) : sb = new StringBuilder(qry);
OracleParameter paramChannel = new OracleParameter() { ParameterName = "CHANNEL_ID", Value = _channelID.ToString(), OracleDbType = OracleDbType.Decimal, Size = 15, Direction = System.Data.ParameterDirection.Input };
//sb.Replace(":CHANNEL_ID", _channelID.ToString());
sb.Replace(":START_DATE", String.Format("'{0:MM/dd/yyyy}'", _startDate));
sb.Replace(":END_DATE", String.Format("'{0:MM/dd/yyyy}'", _endDate));
sb.Replace(":START_TIME", String.Format("'{0:HH:mm}'", _startTime));
sb.Replace(":END_TIME", String.Format("'{0:HH:mm}'", _endTime));
sb.Replace(":PROG_NAME", String.Format("'{0}'", _programName));
using (var ctx = new FITSEntities())
{
foreach (var obj in ctx.GetObjectContext().ExecuteStoreQuery<ProgramAssetCodeWrapper>(sb.ToString(), new { paramChannel }))
{
assetList.Add(new ProgramAssetCodeViewModel
{
IsChecked = false,
ChannelName = obj.CHANNEL_NAME,
AirDate = obj.AIRING_DT.Value,
ProgramName = obj.PROG_NAME,
AssetCode = obj.PROG_BODY_ASSET_CD,
StartTime = obj.START_TIME,
EndTime = obj.END_TIME,
ProgramBodyNo = obj.PROG_BODY_NO.HasValue ? (Int32)obj.PROG_BODY_NO.Value : 0
});
}
}
}
catch
{
}
return assetList;
}
SQL (qry)
SELECT D.CHANNEL_NAME CHANNEL_NAME,
TO_DATE(TO_CHAR(FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', B.PROG_AIR_DT),'MM/DD/YYYY'),'MM/DD/YYYY') AIRING_DT,
A.PROG_NAME,
C.PROG_BODY_ASSET_CD,
FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001'
|| TO_CHAR(B.START_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) START_TIME,
FN_TR_CONVERT_UTC_TIME ('TO_LOCAL',TO_DATE('01/01/2001'
|| TO_CHAR( B.END_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) END_TIME,
ASCII(UPPER(SUBSTR(C.PROG_BODY_ASSET_CD, -1)))-64 PROG_BODY_NO
FROM PROGRAM_MSTR A,
PROG_SKED_DTL B,
PROG_BODY_MSTR C,
CHANNEL_MSTR D
WHERE B.CHANNEL_ID = D.CHANNEL_ID
AND A.PROGRAM_ID = B.PROGRAM_ID
AND B.PROG_SKED_ID = C.PROG_SKED_ID(+)
AND B.CHANNEL_ID = :CHANNEL_ID
AND A.PROG_NAME LIKE ('%'
|| :PROG_NAME
||'%')
AND A.PROG_NAME NOT LIKE 'BS%'
AND A.PROG_NAME NOT LIKE 'B/S%'
AND (TO_DATE(TO_CHAR(FN_TR_CONVERT_UTC_TIME('TO_LOCAL', B.PROG_AIR_DT),'MM/DD/YYYY'),'MM/DD/YYYY') >= TO_DATE(:START_DATE,'MM/DD/YYYY')
AND FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001'
|| TO_CHAR(B.START_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) >= TO_DATE ('01/01/2001 '
|| :START_TIME, 'MM/DD/YYYY HH24:MI'))
AND (TO_DATE(TO_CHAR(FN_TR_CONVERT_UTC_TIME('TO_LOCAL', B.PROG_AIR_DT),'MM/DD/YYYY'),'MM/DD/YYYY') <= TO_DATE(:END_DATE,'MM/DD/YYYY')
AND ((TO_DATE ('01/01/2001 '
|| :START_TIME, 'MM/DD/YYYY HH24:MI') < TO_DATE ('01/01/2001 '
|| :END_TIME, 'MM/DD/YYYY HH24:MI')
AND FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001'
|| TO_CHAR( B.END_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) <= TO_DATE ('01/01/2001 '
|| :END_TIME, 'MM/DD/YYYY HH24:MI'))
OR (TO_DATE ('01/01/2001 '
|| :START_TIME, 'MM/DD/YYYY HH24:MI') >= TO_DATE ('01/01/2001 '
|| :END_TIME, 'MM/DD/YYYY HH24:MI')
AND FN_TR_CONVERT_UTC_TIME ('TO_LOCAL', TO_DATE('01/01/2001'
|| TO_CHAR( B.END_TIME,'HH24:MI'),'MM/DD/YYYY HH24:MI')) <= TO_DATE ('01/02/2001 '
|| :END_TIME, 'MM/DD/YYYY HH24:MI'))))
ORDER BY CHANNEL_NAME,
AIRING_DT,
START_TIME,
END_TIME,
PROG_BODY_NO
I got an example on usage of context.ExecuteStoreQuery<TElement>
here.
And it seems like the second argument must be an array of parameters.
So this code :
ExecuteStoreQuery<ProgramAssetCodeWrapper>(sb.ToString(), new { paramChannel })
must be:
ExecuteStoreQuery<ProgramAssetCodeWrapper>(sb.ToString(), new OracleParameter[]{ paramChannel })
To accommodate multiple parameters, you can do like this:
OracleParameter[] queryParams = new OracleParameter[6];
queryParams[0] = new OracleParameter("START_DATE", OracleDbType.Date, 2, strStartDate, System.Data.ParameterDirection.Input);
queryParams[1] = new OracleParameter("END_DATE", OracleDbType.Date, 4, strEndDate, System.Data.ParameterDirection.Input);
queryParams[2] = new OracleParameter("START_TIME", OracleDbType.TimeStampLTZ, 2, strStartTime, System.Data.ParameterDirection.Input);
queryParams[3] = new OracleParameter("END_TIME", OracleDbType.TimeStampLTZ, 2, strEndTime, System.Data.ParameterDirection.Input);
queryParams[4] = new OracleParameter("PROG_NAME", OracleDbType.Varchar2, 50, strProgName, System.Data.ParameterDirection.Input);
queryParams[5] = new OracleParameter("CHANNEL_ID", OracleDbType.Int32, 50, strChannelID, System.Data.ParameterDirection.Input);
Updated: with proposed proper datatype.
And run the query like this:
var result = ctx.Database.SqlQuery<Object>(qry, queryParams);
If someone wants to add parameters dynamically, here's what I did:
List<OracleParameter> params = new List<OracleParameter>();
params.Add(new OracleParameter("ID", 123));
string query = "SELECT * FROM USERS WHERE ID = :ID";
UserDto = context.ExecuteStoreQuery<UserDto>(query, params.ToArray()).First();
Notice that the List<OracleParameter>
is converted to Array by doing params.ToArray()
, so initially you don't have to know the amount of parameters for the Array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With