Frage

( Haftungsausschluss:.. Ich änderte / verschleiert einige der Variable / Tabelle / Spaltennamen hier aus Sicherheitsgründen Bitte verzeiht mir, wenn etwas ein wenig aus sieht)

Ich bin der Aufbau ein Front-End zu einem Oracle 10g-Datenbank, und ich versuche, ausgelagerten Daten zu erhalten. Abgesehen von Paging, folgenden SubSonic 2.2 Code mir, was ich will, in der Reihenfolge, ich mag es:

var q = new Select()
  .From(AppDb.MyTable.Schema)
  .Where(AppDb.MyTable.DisabledDateColumn).IsNull()
  .OrderDesc(AppDb.MyTable.CreatedDateColumn.ColumnName)

System.Console.Out.Writeline(q.BuildStatement());

Dies ergibt die folgende SQL:

SELECT
    MYSCHEMA.MYTABLE.ID,
    MYSCHEMA.MYTABLE.DISABLED_DATE
FROM
    MYSCHEMA.MYTABLE
WHERE
    MYSCHEMA.MYTABLE.DISABLED_DATE IS NULL
ORDER BY
    CREATED_DATE DESC

Dann versuche ich Paging vorstellen:

var q = new Select()
  .From(AppDb.MyTable.Schema)
  .Where(AppDb.MyTable.DisabledDateColumn).IsNull()
  .OrderDesc(AppDb.MyTable.CreatedDateColumn.ColumnName)
  .Paged(0, 10);

Und es tilgt meine WHERE und ORDER BY-Klauseln:

SELECT * FROM (
    SELECT
        MYSCHEMA.MYTABLE.ID,
        MYSCHEMA.MYTABLE.DISABLED_DATE,
        ROWNUM as row_number
    FROM
        MYSCHEMA.MYTABLE
)
WHERE
    row_number BETWEEN 1 AND 10

Ich bin ganz neu in SubSonic, damit ich weiß nicht, ob das ein Fehler ist, oder ich bin einfach nicht die bevorzugte Art und Weise zu tun, oder wenn Oracle verlangt, dass diese in einem anderen getan werden, mehr Oracle-centric Weg. (Oracle scheint, dass alles zu verlangen.)

Was ich will, falls es nicht offensichtlich ist, ist jede nachfolgende Seite die 10 nächsten meist kürzlich erstellte, nicht behinderte Aufzeichnungen aufzunehmen. Wie kann ich dies tun in SubSonic 2.2?

War es hilfreich?

Lösung

Es sieht aus wie Ihre Abfrage nicht die gleiche SQL als Strom zu erzeugen Oracle Data Provider für SubSonic sollte. Hier ist der relevante Code (ab Zeile 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;

Vielleicht ein Update auf Stromquelle würde den Trick. Wenn es etwas falsch mit dem eigentlichen Provider ist, können Sie es auf die SqlDataProvider für Hinweise, wie vergleichen, was das Problem sein könnte.

Andere Tipps

Ich bin in einer Umgebung mit .NET 2.0 und Oracle 9i R2 und ich lief in das gleiche genaue Problem. Ich benutze SubSonic 2.2.

heruntergeladen ich die Quelle von GitHub und das ist, was ich gefunden habe:

Der Code von @ranomore zitiert (OracleDataProvider.GetSelectSql ()) wird nur aufgerufen, wenn das SubSonic.Query Objekt. Da der OP und ich das Select-Objekt verwenden, die aus dem neueren und leistungsstärkeren SubSonic.SqlQuery Objekt abgeleitet wird, wird OracleDataProvider.GetSelectSql () nie aufgerufen. Stattdessen OracleGenerator.BuildPagedSelectStatement () genannt wird und erzeugt die SQL Sie durch die OP geschrieben sehen. Dieser Code ist fehlerhaft, da sie nie die WHERE und ORDER BY-Klauseln in die Paginierung Abfrage fügt sie erzeugt letztlich.

ersetzt ich den Inhalt BuildPagedSelectStatement () mit etwas basierend auf ANSISqlGenerator.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();
}

Die für mich oben gearbeitet. Hoffe, das hilft anderen!

Oracle fein mit der Top-N-Abfrage wäre, wenn die innere SQL der ersten Anweisung bestehen würde (auch wenn und Ordnung durch).

Also, ich würde sagen, es gibt keinen Oracle spezifischen Grund, sie wegzulassen.

Nie verwendet Unterschall, weiß nicht, ob Sie es tun müssen, um dort anders.

Performance weise, ein Index für DISABLED_DATE, CREATED_DATE sollte es tun (siehe: http://blog.fatalmind.com/2010/07/30/analytic-top-n-queries/ ).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top