使用ROW_NUMBER()
并实现一个静态实用程序函数(如GetPaginatedSQL
在我的代码中),它会自动将您的原始 SQL 查询包装到一个有限/分页的查询中。
这是我使用的一个:
namespace Persistence.Utils
{
public class SQLUtils
{
/// <summary>
/// Builds a paginated/limited query from a SELECT SQL.
/// </summary>
/// <param name="startRow">Start row</param>
/// <param name="numberOfRows">Number/quatity of rows to be expected</param>
/// <param name="sql">Original SQL (without its ordering clause)</param>
/// <param name="orderingClause">MANDATORY: ordering clause (including ORDER BY keywords)</param>
/// <returns>Paginated SQL ready to be executed.</returns>
/// <remarks>SELECT keyword of original SQL must be placed exactly at the beginning of the SQL.</remarks>
public static string GetPaginatedSQL(int startRow, int numberOfRows, string sql, string orderingClause)
{
// Ordering clause is mandatory!
if (String.IsNullOrEmpty(orderingClause))
throw new ArgumentNullException("orderingClause");
// numberOfRows here is checked of disable building paginated/limited query
// in case is not greater than 0. In this case we simply return the
// query with its ordering clause appended to it.
// If ordering is not spe
if (numberOfRows <= 0)
{
return String.Format("{0} {1}", sql, orderingClause);
}
// Extract the SELECT from the beginning.
String partialSQL = sql.Remove(0, "SELECT ".Length);
// Build the limited query...
return String.Format(
"SELECT * FROM ( SELECT ROW_NUMBER() OVER ({0}) AS rn, {1} ) AS SUB WHERE rn > {2} AND rn <= {3}",
orderingClause,
partialSQL,
startRow.ToString(),
(startRow + numberOfRows).ToString()
);
}
}
}
上面的功能可能会有所改进,但只是一个初始实现。
然后,在你的 DAO 中,你应该只做这样的事情:
using (var conn = new SqlConnection(CONNECTION_STRING))
{
using (var cmd = conn.CreateCommand())
{
String SQL = "SELECT * FROM MILLIONS_RECORDS_TABLE";
String SQLOrderBy = "ORDER BY DATE ASC "; //GetOrderByClause(Object someInputParams);
String limitedSQL = GetPaginatedSQL(0, 50, SQL, SQLOrderBy);
DataSet ds = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter();
cmd.CommandText = limitedSQL;
// Add named parameters here to the command if needed...
adapter.SelectCommand = cmd;
adapter.Fill(ds);
// Process the dataset...
}
conn.Close();
}
希望能帮助到你。