限制数据库的结果集

时间:2014-02-21 11:35:25

标签: c# .net database

在我们的C#服务中,我需要为应用程序崩溃方案提供快速修复。

当尝试运行存储过程时,服务崩溃,因为它返回了大量数据。我们正在考虑限制服务方面的结果集。

OracleCommand oraCommand = GetStoredProcedureCommand("SomeProc");
oraParam = new OracleParameter("param1", OracleDbType.Varchar2,               
                                     ParameterDirection.Output);
oraParam.Size = 32000;
oraCommand.Parameters.Add(oraParam);
oraParam = new OracleParameter("param2", OracleDbType.Varchar2, 
                                  ParameterDirection.Input);
oraParam.Value = strSelectedUser;
oraCommand.Parameters.Add(oraParam);

OracleDataAdapter oraDataAdapter = new OracleDataAdapter(oraCommand);
oraDataset = new DataSet();
oraDataAdapter.Fill(oraDataset);//I want to limit the number of records read to the servcie

数据库仍然完全执行proc,这很糟糕,但我们现在没有时间修复它。我们需要将检索到的数据限制为C#服务,从而防止崩溃。

我们如何限制数据?请注意,如果可以使用数据集,我们必须将其作为在服务器中传递的数据集。但如果没有别的办法,我可以重构代码。

3 个答案:

答案 0 :(得分:3)

选项1:

您可以在存储过程中使用SELECT TOP xxx吗?

Oracle SELECT TOP 10 records

这将返回查询的第一个xxxx记录数,允许您指定限制。

您可能想要考虑使用不同的存储过程来使用有限的结果集调用服务,以便其他查询返回所有数据,或者使存储过程具有要作为可选参数返回的记录数。 / p>

选项2:

另一个选择是使用分页一次读取和处理多个记录。

我不确定oracle的语法,但它在SQL中看起来像这样:

这可能是一个更好的选择,因为您仍在处理查询中的所有记录,而不是一次处理所有记录。

        /// <summary>
        /// Gets a list of Customers by name (with paging)
        /// </summary>
        /// <param name="oSageDatabase">The Sage database to query</param>
        /// <param name="startIndex">The start index</param>
        /// <param name="endIndex">The end index</param>
        /// <param name="filter">The filter</param>
        /// <returns>List of suppliers</returns>
        public static List<SLCustomerAccount> GetCustomersByAccountNumber(SageDatabase oSageDatabase, int startIndex, int endIndex, string filter)
        {
            try
            {
                string query = @"
                SELECT * 
                FROM
                (
                    SELECT [SLCustomerAccount].*, 
                           ROW_NUMBER() OVER (ORDER BY [SLCustomerAccount].[CustomerAccountNumber]) AS RowNumber
                    FROM   [SLCustomerAccount] 
                    LEFT JOIN [SLCustomerLocation]
                    ON [SLCustomerAccount].[SLCustomerAccountID]
                    = [SLCustomerLocation].[SLCustomerAccountID]
                    AND [SLCustomerLocation].[SYSTraderLocationTypeID]=0
                    WHERE  [AccountIsOnHold]=0
                    AND    [CustomerAccountNumber] + ' ' + [CustomerAccountName] + ' ' + [CustomerAccountShortName] + ' ' + ISNULL([SLCustomerLocation].[PostCode], '') LIKE @Filter
                ) as p
                WHERE p.RowNumber BETWEEN @StartIndex AND @EndIndex
                ";

                using (SqlCommand oSqlCommand = new SqlCommand(query))
                {
                    oSqlCommand.Parameters.AddWithValue("@StartIndex", startIndex + 1);
                    oSqlCommand.Parameters.AddWithValue("@EndIndex", endIndex + 1);
                    oSqlCommand.Parameters.AddWithValue("@Filter", String.Format("%{0}%", filter));

                    using (DataTable dtSupplier = DataTier.ExecuteQuery(oSageDatabase.ConnectString, oSqlCommand))
                    {
                        return (from DataRow dr
                                in dtSupplier.Rows
                                select new SLCustomerAccount(dr, oSageDatabase)).ToList();
                    }
                }

            }
            catch (Exception)
            {
                throw;
            }
        }

这将允许你从SQL循环说出100条记录,这将有助于内存等,这取决于你对数据的处理。

所以首先运行你将传入查询0表示开始索引,100表示​​结束索引,然后处理记录,并增加变量以获得下一页结果。例如101开始,201结束

答案 1 :(得分:0)

您应该通过修改查询来限制数据库级别的数据。正如WraithNath通过使用SELECT TOP语句对您的帖子所评论的那样,这可以完成。

答案 2 :(得分:0)

您应该使用一些适当的条件或TOP 语句来限制数据库端的数据

但是根据您的要求,如果您想在服务时使用以下代码

oraDataset.Tables[0].AsEnumerable().Take(300);

而不是300,您可以根据您的要求输入数字