C# 如何在亚音速2.2中执行Oracle top-n(分页)查询?
免责声明:出于安全原因,我更改/混淆了此处的一些变量/表/列名。如果有点不对劲,请原谅我 我正在构建Oracle 10g数据库的前端,并尝试获取分页数据。除了分页,下面的亚音速2.2代码按照我想要的顺序提供了我想要的:C# 如何在亚音速2.2中执行Oracle top-n(分页)查询?,c#,oracle,subsonic,pagination,subsonic2.2,C#,Oracle,Subsonic,Pagination,Subsonic2.2,免责声明:出于安全原因,我更改/混淆了此处的一些变量/表/列名。如果有点不对劲,请原谅我 我正在构建Oracle 10g数据库的前端,并尝试获取分页数据。除了分页,下面的亚音速2.2代码按照我想要的顺序提供了我想要的: var q = new Select() .From(AppDb.MyTable.Schema) .Where(AppDb.MyTable.DisabledDateColumn).IsNull() .OrderDesc(AppDb.MyTable.CreatedDat
var q = new Select()
.From(AppDb.MyTable.Schema)
.Where(AppDb.MyTable.DisabledDateColumn).IsNull()
.OrderDesc(AppDb.MyTable.CreatedDateColumn.ColumnName)
System.Console.Out.Writeline(q.BuildStatement());
这将生成以下SQL:
SELECT
MYSCHEMA.MYTABLE.ID,
MYSCHEMA.MYTABLE.DISABLED_DATE
FROM
MYSCHEMA.MYTABLE
WHERE
MYSCHEMA.MYTABLE.DISABLED_DATE IS NULL
ORDER BY
CREATED_DATE DESC
然后我尝试介绍分页:
var q = new Select()
.From(AppDb.MyTable.Schema)
.Where(AppDb.MyTable.DisabledDateColumn).IsNull()
.OrderDesc(AppDb.MyTable.CreatedDateColumn.ColumnName)
.Paged(0, 10);
它删除了我的WHERE和ORDER BY条款:
SELECT * FROM (
SELECT
MYSCHEMA.MYTABLE.ID,
MYSCHEMA.MYTABLE.DISABLED_DATE,
ROWNUM as row_number
FROM
MYSCHEMA.MYTABLE
)
WHERE
row_number BETWEEN 1 AND 10
我是亚音速的新手,所以我不知道这是否是一个bug,或者我只是没有按照首选的方式来做,或者Oracle是否要求以一种不同的、更以Oracle为中心的方式来做。甲骨文似乎对一切都有这样的要求
如果不明显的话,我想要的是每个后续页面包含10条最近创建的非禁用记录。如何在亚音速2.2中做到这一点?如果内部SQL包含第一条语句,包括where和order by,则Oracle可以使用Top-N查询 所以,我要说的是,没有甲骨文明确的理由省略它们 从未使用过亚音速,不知道你是否需要在那里做不同的事情
就性能而言,禁用日期、创建日期的索引应该可以实现如下功能:。如果内部SQL包含第一条语句,包括where和order by,则Oracle可以使用Top-N查询 所以,我要说的是,没有甲骨文明确的理由省略它们 从未使用过亚音速,不知道你是否需要在那里做不同的事情
就性能而言,禁用日期、创建日期的索引应该起到如下作用:。看起来您的查询生成的SQL与当前查询生成的SQL不一样。以下是从第852行开始的相关代码:
if(qry.PageIndex < 0)
query = String.Format("{0} {1} FROM {2}.{3} {4} {5}",select ,columns, table.SchemaName, table.Name, where, order);
else
{
int start = qry.PageIndex * qry.PageSize;
int end = (qry.PageIndex + 1) * qry.PageSize;
const string cteFormat =
"WITH pagedtable AS (SELECT {0}, ROW_NUMBER () OVER ({1}) AS rowindex FROM {2}.{3} {4}) SELECT {5}, rowindex FROM pagedtable WHERE rowindex >= {6} AND rowindex < {7} ORDER BY rowindex";
query = string.Format(cteFormat, columns, order,table.SchemaName, table.Name, where, columns.Replace(table.Name + ".", String.Empty), start, end);
}
return query;
也许对当前源代码进行更新就可以做到这一点。如果实际的提供程序有问题,您可以将其与SqlDataProvider进行比较,以获得可能存在问题的提示。看起来您的查询生成的SQL与当前应生成的SQL不一样。以下是从第852行开始的相关代码:
if(qry.PageIndex < 0)
query = String.Format("{0} {1} FROM {2}.{3} {4} {5}",select ,columns, table.SchemaName, table.Name, where, order);
else
{
int start = qry.PageIndex * qry.PageSize;
int end = (qry.PageIndex + 1) * qry.PageSize;
const string cteFormat =
"WITH pagedtable AS (SELECT {0}, ROW_NUMBER () OVER ({1}) AS rowindex FROM {2}.{3} {4}) SELECT {5}, rowindex FROM pagedtable WHERE rowindex >= {6} AND rowindex < {7} ORDER BY rowindex";
query = string.Format(cteFormat, columns, order,table.SchemaName, table.Name, where, columns.Replace(table.Name + ".", String.Empty), start, end);
}
return query;
也许对当前源代码进行更新就可以做到这一点。如果实际的提供程序有问题,您可以将其与SqlDataProvider进行比较,以了解可能存在的问题。我在使用NET 2.0和Oracle 9i R2的环境中,遇到了相同的问题。我用的是亚音速2.2 我从GitHub下载了源代码,我发现: @ranomore OracleDataProvider.GetSelectSql引用的代码仅在使用SubSonic.Query对象时调用。由于OP和我自己使用的Select对象是从更新且功能更强大的SubSonic.SqlQuery对象派生的,因此永远不会调用OracleDataProvider.GetSelectSql。取而代之的是,调用并生成OP发布的SQL。这段代码有缺陷,因为它从未将WHERE和ORDER by子句添加到它最终生成的分页查询中 我将BuildPagedSelectStatement的内容替换为基于AnisqlGenerator.BuildSelectStatement的内容:
public override string BuildPagedSelectStatement()
{
int startnum = query.PageSize * query.CurrentPage + 1;
int endnum = query.PageSize * query.CurrentPage + query.PageSize;
string orderBy = String.Empty;
if (this.query.OrderBys.Count > 0)
orderBy = GenerateOrderBy();
//The ROW_NUMBER() function in Oracle requires an ORDER BY clause.
//In case one is not specified, we need to halt and inform the caller.
if(orderBy.Equals(String.Empty))
throw new ArgumentException("There is no column specified for the ORDER BY clause", "OrderBys");
System.Text.StringBuilder sql = new System.Text.StringBuilder();
//Build the command string
sql.Append("WITH pagedtable AS (");
sql.Append(GenerateCommandLine());
//Since this class is for Oracle-specific SQL, we can add a hint
//which should help pagination queries return rows more quickly.
//AFAIK, this is only valid for Oracle 9i or newer.
sql.Replace("SELECT", "SELECT /*+ first_rows('" + query.PageSize + "') */");
sql.Append(", ROW_NUMBER () OVER (");
sql.Append(orderBy);
sql.Append(") AS rowindex ");
sql.Append(Environment.NewLine);
sql.Append(GenerateFromList());
sql.Append(GenerateJoins());
sql.Append(GenerateWhere());
if (query.Aggregates.Count > 0)
{
sql.Append(GenerateGroupBy());
sql.Append(Environment.NewLine);
sql.Append(GenerateHaving());
}
sql.Append(") SELECT * FROM pagedtable WHERE rowindex >= ");
sql.Append(startnum);
sql.Append(" AND rowindex < ");
sql.Append(endnum);
sql.Append(" ORDER BY rowindex");
return sql.ToString();
}
以上这些对我很有用。希望这能帮助别人 我在一个使用Net2.0和Oracle 9i R2的环境中,遇到了同样的问题。我用的是亚音速2.2 我从GitHub下载了源代码,我发现: @ranomore OracleDataProvider.GetSelectSql引用的代码仅在使用SubSonic.Query对象时调用。由于OP和我自己使用的Select对象是从更新且功能更强大的SubSonic.SqlQuery对象派生的,因此永远不会调用OracleDataProvider.GetSelectSql。取而代之的是,调用并生成OP发布的SQL。这段代码有缺陷,因为它从未将WHERE和ORDER by子句添加到它最终生成的分页查询中 我将BuildPagedSelectStatement的内容替换为基于AnisqlGenerator.BuildSelectStatement的内容:
public override string BuildPagedSelectStatement()
{
int startnum = query.PageSize * query.CurrentPage + 1;
int endnum = query.PageSize * query.CurrentPage + query.PageSize;
string orderBy = String.Empty;
if (this.query.OrderBys.Count > 0)
orderBy = GenerateOrderBy();
//The ROW_NUMBER() function in Oracle requires an ORDER BY clause.
//In case one is not specified, we need to halt and inform the caller.
if(orderBy.Equals(String.Empty))
throw new ArgumentException("There is no column specified for the ORDER BY clause", "OrderBys");
System.Text.StringBuilder sql = new System.Text.StringBuilder();
//Build the command string
sql.Append("WITH pagedtable AS (");
sql.Append(GenerateCommandLine());
//Since this class is for Oracle-specific SQL, we can add a hint
//which should help pagination queries return rows more quickly.
//AFAIK, this is only valid for Oracle 9i or newer.
sql.Replace("SELECT", "SELECT /*+ first_rows('" + query.PageSize + "') */");
sql.Append(", ROW_NUMBER () OVER (");
sql.Append(orderBy);
sql.Append(") AS rowindex ");
sql.Append(Environment.NewLine);
sql.Append(GenerateFromList());
sql.Append(GenerateJoins());
sql.Append(GenerateWhere());
if (query.Aggregates.Count > 0)
{
sql.Append(GenerateGroupBy());
sql.Append(Environment.NewLine);
sql.Append(GenerateHaving());
}
sql.Append(") SELECT * FROM pagedtable WHERE rowindex >= ");
sql.Append(startnum);
sql.Append(" AND rowindex < ");
sql.Append(endnum);
sql.Append(" ORDER BY rowindex");
return sql.ToString();
}
以上这些对我很有用。希望这能帮助别人