2016-07-26 17 views
1

ich einen Business-Service zu schreiben, die alle Datensätze in einem BC iterieren muss, und einige von ihnen löschen:Wie kann ich Datensätze in einer Schleife löschen?

bc.ExecuteQuery(ForwardBackward); 
var isRecord = bc.FirstRecord(); 
while (isRecord) { 
    if (...) { 
    bc.DeleteRecord(); 
    } 
    isRecord = bc.NextRecord(); 
} 

jedoch DeleteRecord moves the cursor to the next one, also würde ich einen Datensatz für jeden ein Wesen werden Skipping gelöscht, was ich nicht will. Gibt es einen Standard-ish Weg, um dies zu lösen?

Ich denke, ich könnte nur zwei Schleifen machen, eine für die Überprüfung und eine andere für die Löschung ... es würde funktionieren, aber es ist einfach albern, zweimal über die Datensätze zu iterieren, es muss einen besseren Weg geben direkt auf, wenn (...) Bedingung abhängig

bc.ExecuteQuery(ForwardBackward); 
var isRecord = bc.FirstRecord(); 
var list = []; 
while (isRecord) { 
    if (...) { 
    list.push(bc.GetFieldValue("Id")); 
    } 
    isRecord = bc.NextRecord(); 
} 

bc.ClearToQuery(); 
bc.SetSearchSpec("Id", "='" + list.join("' OR ='") + "'"); // "='1-ABCD' OR ='1-1234'" 
bc.ExecuteQuery(ForwardBackward); 
while (bc.FirstRecord()) { 
    bc.DeleteRecord(); 
} 
+1

Das Problem ist, dass DeleteRecord nicht zurückgibt etwas. Andernfalls könnte die Logik leicht mit einer if-Schleife neu angeordnet werden. Ihre Logik, zu einer Liste zu wechseln und selektiv zu löschen, sieht optimiert aus. –

Antwort

1

Solution:

  • wenn es eine einfache Bedingung ist, die zu einer Suche Ausdruck umgewandelt werden kann, dann einfach können Sie einfach: machen Sie eine Abfrage und löschen Sie alles das wurde gefunden.

  • Wenn es sich um eine komplexe Bedingung handelt, die nicht als Suchspezifikation implementiert werden kann, können Sie dies auf zwei Arten tun (beide haben ihre eigenen Nachteile): a) Verwenden Sie eine peinliche Kombination von DeleteRecord und PreviousRecord. b) zweite Methode erstellen, die einzelnen Datensatz löschen wird und es für jeden Datensatz aufrufen, die die Bedingung, dass so etwas

    function deleteRecord(sId:chars) { 
        ... 
        bc.SetSearchSpec("Id", sId); 
        bc.ExecuteQuery(ForwardOnly); 
        if (bc.FirstRecord()) { 
        bc.DeleteRecord(); 
        } 
    } 
    ... 
    bc.ExecuteQuery(ForwardBackward); 
    var isRecord = bc.FirstRecord(); 
    while (isRecord) { 
        if (...) { 
        deleteRecord(bc.GetFieldValue("Id")); 
        } 
        isRecord = bc.NextRecord(); 
    } 
    ... 
    
  • erfüllen

Ihre Lösung und Option c), aber es wird nicht funktionieren, wenn Die ID-Liste ist zu groß, da eine solche Abfrage zu einer großen SQL-Anweisung führt und die SQL-Abfragegröße für Datenbanken begrenzt ist (und DBA wird sich nicht freuen, solche Abfragen in Protokollen zu sehen).

Ich bevorzuge Option b). Sie können es optimieren, indem Sie in Ihrer Hauptfunktion eine zweite Instanz desselben BCs erstellen und diese über die Funktion deleteRecord übergeben.

+0

In diesem speziellen escenario war die Bedingung ziemlich einfach und ich habe es zu einer Suchspezifikation verschoben, mit einem "while FirstRecord, DeleteRecord". Ich war mehr daran interessiert herauszufinden, wie es anderen Menschen im komplexen Fall geht. Ich denke, ich bevorzuge deine b) Option auch, es ist sauberer. – AJPerez

0

Are speichert den Wert eines ersten Datensatzes in var und überprüft dann in der Schleife, ob Datensätze präsentiert werden. Ich schlage vor, dass Sie vorwärts und rückwärts versuchen. Der Wert von var wird inkrementiert. Also, innerhalb der while-Schleife platzieren Sie den Befehl element zurück und so speichert var jetzt das vorherige Element. Nach dem Ausführen der Schleife. Sie können problemlos zum nächsten Element wechseln.

+1

pls bieten einige Beispiele – JayKandari

1

Da Sie ForwardBackward tun, könnten Sie einfach einen PreviousRecord Anruf nach dem Löschen hinzufügen:

bc.ExecuteQuery(ForwardBackward); 
var isRecord = bc.FirstRecord(); 
while (isRecord) { 
    if (...) { 
    bc.DeleteRecord(); 
    bc.PreviousRecord(); 
    } 
    isRecord = bc.NextRecord(); 
} 

Oder einfach tun, um die Schleife rückwärts:

bc.ExecuteQuery(ForwardBackward); 
var isRecord = bc.LastRecord(); 
while (isRecord) { 
    if (...) { 
    bc.DeleteRecord(); 
    } 
    isRecord = bc.PreviousRecord(); 
} 
+0

Definitiv sieht der zweite besser aus. Es gibt jedoch ein Problem mit beiden: "Wenn Sie die DeleteRecord-Methode für den letzten Datensatz verwenden, zeigt der Cursor auf nichts". Ich bin mir nicht sicher, ob ich einen PreviousRecord von dort aus machen kann. – AJPerez

+0

@AJPerez der erste würde dann kein Problem geben, denn selbst wenn 'PreviousRecord' nicht funktionieren würde, würde' NextRecord' dann falsy zurückgeben, denke ich. Aber ja, siebel BCs würden definitiv entweder von 'DeleteRecord()' etwas zurückgeben, oder eine 'GetCurrent() 'Methode oder etwas haben – Jcl

+0

Ich dachte, du könntest Recht haben, also habe ich sie gerade ausprobiert ... aber etwas komisches passiert: D. Wenn ich zum Beispiel 4 Datensätze im BC habe und den zweiten Code (ohne 'if') ausführe, löscht er den 4., überspringt 3 und löscht 2 und 1. Der Aufruf von Previous, wenn ich gerade den letzten Datensatz gelöscht habe, funktioniert nicht scheinen zu gut zu funktionieren. Der erste Code überspringt auch eines der Elemente, obwohl ich in diesem Fall nicht überprüft habe, welches oder wenn es übersprungen wird. – AJPerez