Frage

Ich baue einen Objektauftrag in meiner Datenbank zu suchen. Es gibt eine Reihe von möglichen Parametern, die der Anwender festlegen kann, und sie können so viele eingestellt, wie dann für jede Suche will. Ich habe Setter-Methoden erstellt alle Parameter für die Suche benötigt sammeln.

Meine Frage ist. Was wäre "best practice"

  1. Speichern der Parameter und den Aufbau der WHERE Klausel, wenn die doSearch Methode aufgerufen wird,
  2. Erstellen der WHERE Klausel als Parameter festgelegt werden

Ich möchte den Grund für jede Empfehlung verstehen.

Beachten Sie, dass das Objekt für jede Suche instatiated ist, so habe ich keine Sorgen um eine zweite Suche mit verschiedenen Parametern.

War es hilfreich?

Lösung

Sie sollten den Code für Ihre Bestellung Suche aus dem Code trennen, die die SQL baut. Die SQL sollte in einem Derivat (oder Strategie Derivat) der OrderSearch Klasse gebaut werden. Sobald Sie diese Trennung gemacht haben, tut es nicht wirklich wichtig , wenn Sie die SQL bauen.

Um dies ein wenig schlicht. Bei einer benannten OrderSearch Klasse, die eine Reihe von Setter-Methoden für die Suchkriterien hat, möchten Sie eine Unterklasse namens OrderSearchSQLBuilder haben. Beachten Sie, dass die Unterklasse auf der Basisklasse abhängt, und dass die Basisklasse ist unabhängig von der Unterklasse. Dies ist sehr wichtig. Diese Unabhängigkeit ermöglicht es Ihnen, außer Acht zu lassen, ob die SQL in den Setter-Methoden gebaut werden, oder in der Suchmethode. Siehe Das Dependency Inversion Principle (DIP) .

Wenn Sie diese Art von Trennung haben, können Sie die Ableitung mit anderen Strategien ersetzen. Zum Beispiel, wenn Sie Ihre Anwendung testen, ohne dass es auf die SQL-Datenbank verbinden mögen, können Sie einen Dummy in-RAM-Datenbank erstellen und ein Derivat von OrderSearch erstellen, die mit dieser Dummy-Datenbank behandelt. Der Rest der Anwendung wäre völlig ahnungslos, und die Tests dann der Schrecken von Datenbankverbindungen unabhängig sein würde, bereits vorhandene Daten, usw.

Andere Tipps

In Ihrer Methode, verwenden Sie einfach die Parameter in Ihrer dynamischen SQL, die die Suche der Fall ist. Auf diese Weise die where-Klausel ist kurz vor dem SQL bekommen Lauf gebaut. Sie werden einfach die Suchparameter in Ihre Methode als Argumente übergeben.

So etwas ...

<cffunction name="getByAttributesQuery" access="public" output="false" returntype="query">
    <cfargument name="id" type="numeric" required="false" />
    <cfargument name="userName" type="string" required="false" />
    <cfargument name="firstName" type="string" required="false" />
    <cfargument name="lastName" type="string" required="false" />
    <cfargument name="createdAt" type="date" required="false" />
    <cfargument name="updatedAt" type="date" required="false" />
    <cfargument name="orderby" type="string" required="false" />

    <cfset var qList = "" />        
    <cfquery name="qList" datasource="#variables.dsn#">
        SELECT  
            id,
            userName,
            firstName,
            lastName,
            createdAt,
            updatedAt
        FROM    users
        WHERE       0=0
    <cfif structKeyExists(arguments,"id") and len(arguments.id)>
        AND id = <cfqueryparam value="#arguments.id#" CFSQLType="cf_sql_integer" />
    </cfif>
    <cfif structKeyExists(arguments,"userName") and len(arguments.userName)>
        AND userName = <cfqueryparam value="#arguments.userName#" CFSQLType="cf_sql_varchar" />
    </cfif>
    <cfif structKeyExists(arguments,"firstName") and len(arguments.firstName)>
        AND firstName = <cfqueryparam value="#arguments.firstName#" CFSQLType="cf_sql_varchar" />
    </cfif>
    <cfif structKeyExists(arguments,"lastName") and len(arguments.lastName)>
        AND lastName = <cfqueryparam value="#arguments.lastName#" CFSQLType="cf_sql_varchar" />
    </cfif>
    <cfif structKeyExists(arguments,"createdAt") and len(arguments.createdAt)>
        AND createdAt = <cfqueryparam value="#arguments.createdAt#" CFSQLType="cf_sql_timestamp" />
    </cfif>
    <cfif structKeyExists(arguments,"updatedAt") and len(arguments.updatedAt)>
        AND updatedAt = <cfqueryparam value="#arguments.updatedAt#" CFSQLType="cf_sql_timestamp" />
    </cfif>
    <cfif structKeyExists(arguments, "orderby") and len(arguments.orderBy)>
        ORDER BY #arguments.orderby#
    </cfif>
    </cfquery>

    <cfreturn qList />
</cffunction>

Sie die nicht bauen, wo Klausel, bevor es benötigt, um die Suche auszuführen. Sie können mit einer Benutzeroberfläche am Ende, die Parameter in Iterationen Feeds und Sie nicht wissen, wenn Sie alles haben. Auch Sie können nie die Suche ausführen, warum also Sorgen über die where-Klausel.

Ich glaube es nicht viel Unterschied macht, aber ich denke, es ist besser Praxis scheint die WHERE-Klausel, wenn Sie doSearch zu bauen. Ich glaube nicht, dass es in der Verantwortung eines Setter für einen Parameter einer WHERE-Klausel Zeichenfolge irgendwo hinzuzufügen sein sollte.

Auf einer SQLServer-Datenbank ist es effizienter, alle Parameter in der where-Klausel aufzunehmen, anstatt sie im Fluge zu bauen. Dann eine Datenbank Index haben, der alle Spalten enthält sucht Sie. Dadurch wird sichergestellt, der Index wird immer dann verwendet, wenn die Anweisung ausgeführt wird.

dosn't ganz klingen wie Ihre Abstraktion ganz richtig ist.

Suche kann als Methode eines „Aufträge“ Objekt besser sein. Pass in den Parametern der Suchfunktion und bauen die Abfrage manuell als vorgeschlagen RUSS . Alles, was auf Aufträge spezifisch ist, anstatt die Suche kann dann auf Befehl init-Methode festgelegt werden.

Es ist möglich, dass Sie ein Bestellung Suchobjekt bauen mögen, aber dies soll über Bestellungen erfolgen, das Objekt Ihre Front-End-Code einfach zu halten.

Option 1 ist die beste Wahl. Option 2 klingt gefährlich. Was passiert, wenn ein Parameter aktualisiert wird? Wie ersetze Sie es in Ihrer WHERE-Klausel?

Ich würde so etwas tun:

<cffunction name="doSearch" access="public" output="false" returntype="query">        
    <cfset var qList = "" />
    <cfquery name="qList" datasource="#variables.dsn#">
       SELECT
           ...
       FROM
           ...
       WHERE 0=0 
         <cfif len(getID())>
           AND id = <cfqueryparam value="#getID()#" CFSQLType="cf_sql_integer" />
         </cfif>       
         <cfif len(getUserName())>
           AND userName = <cfqueryparam value="#getUserName()#" CFSQLType="cf_sql_varchar" />
         </cfif>
    </cfquery>
    <cfreturn qList />
</cffunction>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top