2016-07-26 3 views
2

Ich habe ein fkInternal berechnetes Feld vom Typ ftBlob (in einem TClientDataSet), das Blobs in einer DataSnap-Clientanwendung enthält.Erkennung von leerem/gefülltem TBlobField schlägt fehl

Das Feld ist anfänglich leer, wir füllen es nur, wenn die Blobdaten tatsächlich benötigt werden *.

Dies ist der Code, der die Daten von der Serveranwendung zieht:

var 
    lBlobStream: TStream; 
    lBlobField : TBlobField; 

with DataSet do 
begin 
    lBlobField := TBlobField(FieldByName(sExpItmFileFile)); // The fkInternalCalc blob 
    try 
    // Retrieve the blob stream (calculated field) separately when we don't yet have data: 
    if lBlobField.isNull then 
    begin 
     Edit; 
     lBlobStream := CreateBlobStream(lBlobField, bmWrite); 
     DownLoadAttachmentBlob(FieldByName(sExpItmFileID).Asinteger,lBlobStream); 
     Post; 
     ... 
    end; 

Die Blob-Daten fein abgerufen werden.
Mein Problem ist mit dem if lBlobField.isNull Test: das nächste Mal, wenn wir in diesem Code kommen (der Datensatz bleibt auf dem gleichen Datensatz, ApplyUpdates wird in der Zwischenzeit aufgerufen) dieser Wert ist immer noch wahr.
Ich habe auch versucht, die Eigenschaften Size, sie DataSize, BlobSize, sind über alle 0.

Wie kann ich überprüfen, ob mein TBlobField Daten zu überprüfen?
(Oder bin ich etwas falsch in diesem Code zu tun?)

* Grund: Wir wollen nicht in all diese Daten ziehen; tatsächlich Laden ein TClientDataSet mit vielen Klecksen ‚Paket zu groß‘ Fehler in den RemObjects Komponenten gibt, die wir

Edit 1 verwenden: Es hat wahrscheinlich etwas mit dem Inhalt des Feldes nicht ‚kleben‘ - in einem anderen Teil Der Code direkt nach dem Post lBlobField.Value ist leer.

Edit 2: Dies ist ein Datensatz mit einer Abfrage über 3 verschachtelte Tabellen. DataSet ist die dritte Ebene TClientDataSet und hier müssen die Datenblobs das fkInternalCalc Feld geschrieben werden (daher die bmWrite, die Edit und die Post), nur wenn sie tatsächlich benötigt werden. Sie werden über einen separaten Client-Server-Kanal von DownLoadAttachmentBlob abgerufen. Dies ruft die Datensatz-ID als Eingabe ab und setzt die Blob-Daten in den zweiten Parameter (lBlobStream). Das (verschachtelte) Dataset enthält alle anderen Felder der Tabelle der 3. Ebene (wie ID sExpItmFileID), aber nicht seine Blobdaten. DownLoadAttachmentBlob funktioniert OK.
Sobald ein Blob in das Feld cal gelesen wird, wollen wir es behalten (nicht zweimal abrufen).

+1

Sorry, wenn nur Rauschen, aber Sie den BLOB-Stream mit dem Modus 'bmWrite' erstellen, obwohl Sie von ihm lesen erscheinen:

Daher wird das entsprechende Codeteil sollte? Auch wenn Sie nicht wissen, was 'DownLoadAttachmentBlob()' genau macht, ist es richtig, dass das Blobfeld 'sExpItmFileFile' zu ​​sein scheint, aber Sie'SExpItmFileID' an die Funktion übergeben? –

+0

@TomBrunberg Sorry für die Verwirrung ;-) Siehe Edit 2. –

+0

Verse nicht deinen Post mit * Edit 1 * und * Edit 2 *. Wir können sehen, welche Änderung geändert wurde, indem wir uns die [Revisionshistorie] (http://stackoverflow.com/posts/38588645/revisions) ansehen. Bearbeiten Sie einfach den Post und fügen Sie die Details hinzu, als ob Sie sie an erster Stelle geschrieben hätten. –

Antwort

1

die Lösung selbst gefunden, und es mir völlig Schikanen:

Die TStream (var lBlobStream) hat vor dem Aufruf des Dataset Post-Methode befreit werden.

Edit; 
lBlobStream := CreateBlobStream(lBlobField, bmWrite); 
DownLoadAttachmentBlob(FieldByName(sExpItmFileID).Asinteger,lBlobStream); 
lBlobStream.Free; 
Post; 
+1

Das scheint mir nicht verwirrend. TFileStream schreibt die Datei auch, wenn sie freigegeben wird. –

0

Ich würde dieses Problem in SQL lösen.

Fügen Sie in Ihrer SELECT-Anweisung ein zusätzliches Feld hinzu, das angibt, ob das BLOB-Feld leer ist oder nicht.

select *, ifnull(BlobField, 1, 0) as BlobNull from mytable 

Jetzt können Sie nur das Feld BlobNull abfragen. Natürlich müssen Sie die Funktion IfNull an die in Ihrer Datenbank verfügbare Syntax anpassen. Eine Alternative könnte sein, den Test einfach als boolesches Feld zu verwenden.

select *, (Blobfield is null) as BlobNull from mytable 

Noch besser wäre es nicht alle Felder aus, sondern ziehen Sie einfach die benötigten Felder und gefüllt blobfields ausschließen where-Klausel, aber ich bin nicht sicher, dass Ihr Anwendungsfall dies zulässt.

+0

Der Vorteil der Lösung in SQL ist, dass Sie die Blobs nicht über den Draht ziehen müssen, wenn Sie sie nicht verwenden, was die Geschwindigkeit stark erhöht. – Johan