【问题标题】:Using OracleParameter in ExecuteStoreQuery Error Msg : " Value does not fall within the expected range."在 ExecuteStoreQuery 错误消息中使用 OracleParameter:“值不在预期范围内。”
【发布时间】:2014-07-23 16:51:00
【问题描述】:

为了防止SQLinjection。我需要将我的代码从简单的String 更改为OracleParameter。此外,我需要绕过 LINQ,因为它在我的 WHERE CLAUSE 中存在限制,如下所示,并持续获得更好的性能。顺便说一句,在我使用 OracleParameter 之前,这段代码就可以工作了。

我收到此错误消息“值不在预期范围内”。 我的代码有什么问题或缺少什么,特别是在 OracleParameterExecuteStoreQuery 部分?

我正在使用以下内容:

  1. VS 2010
  2. Oracle 11gR2
  3. C#
  4. EntityFramework 4.3.1

代码(.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

【问题讨论】:

  • 如何修复缩进/行长以使其可读?
  • 免责声明:在我在这里提问之前,我会尽力在谷歌上搜索这个错误。 +1
  • 为什么你把CHANNEL_ID注释掉了,但它存在于查询字符串中?
  • ExecuteStoreQuery 的第二个参数中是否需要new {}?或者它必须是新的OracleParameter[] {}
  • 没有 ORA 错误代码@ChristianMark ..也许这个错误只在前端..我想我知道如何解决这个.. :)))

标签: c# oracle entity-framework


【解决方案1】:

我有一个使用 context.ExecuteStoreQuery&lt;TElement&gt; here. 的例子

似乎第二个参数必须是一个参数数组。

所以这段代码:

ExecuteStoreQuery&lt;ProgramAssetCodeWrapper&gt;(sb.ToString(), new { paramChannel })

必须是:

ExecuteStoreQuery<ProgramAssetCodeWrapper>(sb.ToString(), new OracleParameter[]{ paramChannel })

【讨论】:

  • 我禁用了我的智能感知......我没有注意到......像魅力一样工作......谢谢......:P
【解决方案2】:

要容纳多个参数,您可以这样做:

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);

更新:建议的正确数据类型。

然后像这样运行查询:

var result = ctx.Database.SqlQuery<Object>(qry, queryParams);

【讨论】:

  • 啊哈..我看到您使用DbContext 而不是ObjectContext..即使在ExecuteStoreQuery 中您也可以编写多个参数...:D
  • 是的@OLRAC,尽管有minor problem in IN CLAUSE but with workaround,我什至在ReportParameters 中使用它。
【解决方案3】:

如果有人想动态添加参数,我就是这样做的:

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();

请注意,List&lt;OracleParameter&gt; 通过执行params.ToArray() 转换为数组,因此最初您不必知道数组的参数数量。

【讨论】:

    猜你喜欢
    • 2013-10-23
    • 1970-01-01
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    相关资源
    最近更新 更多