简体   繁体   English

在子查询中绕过排序以获取查询的记录数

[英]Bypass order by in subquery for getting recordcount of query

I have a function which executes a datareader with a given commandtext and invokes a given action for every data record returned by the reader. 我有一个函数,该函数使用给定的命令文本执行数据读取器,并为读取器返回的每个数据记录调用给定的操作。

Since the datareader is a forward-only reader i can not get the count of rows from the datareader. 由于数据读取器是仅向前的读取器,因此我无法从数据读取器获取行数。 For invoking a progressbar i have to know the count of the records my datareader will return. 对于调用进度条,我必须知道我的数据读取器将返回的记录数。

My current attempt looks like this: 我当前的尝试如下所示:

protected void RunConversion(string commandText, Action<IDataRecord> actionConversion)
{
    try
    {
        var curIndex = 0;
        var maxIndex = this.Source.ExecuteScalar<int?>($"SELECT COUNT(*) FROM ({commandText}) AS QUERY"); //Here i try to get the count of rows from the result 

        OnProgress?.Invoke(0);

        foreach (var dataRecord in this.Source.ExecuteReader(commandText))
        {
            try
            {
                actionConversion?.Invoke(dataRecord);
            }
            catch (Exception e)
            {
                OnReport?.Invoke($"Error: {e}{Environment.NewLine}");
            }
            finally
            {
                OnProgress?.Invoke((int)((double)++curIndex / maxIndex * 100f));
            }
        }
    }
    catch (Exception e)
    {
        OnReport?.Invoke($"Fatal Error: {e}{Environment.NewLine}");
        OnProgress?.Invoke(100);
    }
}

The problem is, sometimes the commandText-Parameter contains a query which includes order by... without using top the order by is not allowed in subqueries. 问题是,有时commandText-Parameter包含一个包含order ...的查询,而没有使用top,则子查询中不允许使用order by。

Another attempt would be to provide a thrid parameter which is a query that only counts the result of my current commandText-Parameter. 另一个尝试是提供一个第三参数,这是一个仅对我当前commandText-Parameter的结果进行计数的查询。 This would be no nice solution, since i have to write two queries and they can be pretty complex. 这将不是一个很好的解决方案,因为我必须编写两个查询,而且它们可能非常复杂。

Any idea for a simple solution? 任何简单解决方案的想法?

You mention you can't use the count because you are using a DataReader . 您提到不能使用计数,因为您正在使用DataReader Are you showing a Progress Bar for the query? 您是否正在显示查询的进度栏? If so, I would suggest that instead of a progress bar, simply show a "wait" icon rather than executing a query twice and extending the time that the user has to wait just to display how long they will be waiting. 如果是这样,我建议不要显示进度条,而只是显示一个“等待”图标,而不是执行两次查询并延长用户必须等待的时间,以显示他们将等待多长时间。

With that in mind, you have two options. 考虑到这一点,您有两个选择。 The first being to do away with the progress bar and the SELECT COUNT(*) FROM (...); 首先是取消进度条和SELECT COUNT(*) FROM (...); and simply pass the query as-is. 并按原样传递查询。 Then when you execute it and get a result set back, you can count the records if you still need to show a progress bar for record processing. 然后,在执行它并返回结果集时,如果仍然需要显示进度条以进行记录处理,则可以对记录进行计数。 Granted, this has the downside of adding data transfer overhead to your operation if you aren't going to use the actual data, so it is up to you if it is worth that little extra debt. 诚然,如果您不打算使用实际数据,这将给您的操作增加数据传输开销,因此由您自己决定是否值得承担少得多的额外债务。

Your second option would be to simply remove the ORDER BY portion of any queries by doing something like the following: 第二种选择是通过执行以下操作来简单地删除任何查询的ORDER BY部分:

public string RemoveOrderBy(string query)
{
    return query.SubString(0, query.IndexOf("ORDER BY"));
}

This would get rid of any ORDER BY statements, but if you have any other things that may not work in a sub-query you would have to account for them in the same way as above. 这将摆脱任何ORDER BY语句,但是如果您有其他可能无法在子查询中使用的东西,则必须以与上述相同的方式对其进行说明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM