Freigeben über


Vermeiden von Konflikten mit Datenbankvorgängen in FILESTREAM-Anwendungen

Anwendungen, die SqlOpenFilestream() verwenden, um Win32-Dateihandles zum Lesen oder Schreiben von FILESTREAM BLOB-Daten zu öffnen, können Konfliktfehler aufgrund von Transact-SQL-Anweisungen aufweisen, die in einer gemeinsamen Transaktion verwaltet werden. Dazu gehören Transact-SQL oder MARS-Abfragen, die eine lange Zeit in Anspruch nehmen, um die Ausführung abzuschließen. Anwendungen müssen sorgfältig entworfen werden, um diese Arten von Konflikten zu vermeiden.

Wenn SQL Server-Datenbankmodul oder -Anwendungen versuchen, FILESTREAM BLOBs zu öffnen, überprüft das Datenbankmodul den zugeordneten Transaktionskontext. Das Datenbankmodul ermöglicht oder verweigert die Anforderung basierend darauf, ob der geöffnete Vorgang mit DDL-Anweisungen, DML-Anweisungen, Abrufen von Daten oder Verwalten von Transaktionen arbeitet. In der folgenden Tabelle wird gezeigt, wie das Datenbankmodul bestimmt, ob eine Transact-SQL-Anweisung basierend auf dem Typ der dateien zulässig oder verweigert wird, die in der Transaktion geöffnet sind.

Transact-SQL-Anweisungen Geöffnet zum Lesen Zum Schreiben geöffnet
DDL-Anweisungen, die mit Datenbankmetadaten arbeiten, z. B. CREATE TABLE, CREATE INDEX, DROP TABLE und ALTER TABLE. Zulässig Werden blockiert und fehlschlagen aufgrund eines Timeouts.
DML-Anweisungen, die mit den Daten arbeiten, die in der Datenbank gespeichert sind, z. B. UPDATE, DELETE und INSERT. Zulässig Verweigert
Auswählen Zulässig Zulässig
Transaktion abschließen Verweigert* Verweigert*.
TRANSAKTION SPEICHERN Verweigert* Verweigert*
Rollback Erlaubt* Erlaubt*

* Die Transaktion wird abgebrochen, und offene Handles für den Transaktionskontext werden ungültig. Die Anwendung muss alle geöffneten Handles schließen.

Beispiele

Die folgenden Beispiele zeigen, wie Transact-SQL Anweisungen und FILESTREAM Win32-Zugriff Konflikte verursachen können.

Ein. Öffnen eines FILESTREAM-BLOB für Schreibzugriff

Das folgende Beispiel zeigt die Auswirkung des Öffnens einer Datei nur für schreibgeschützten Zugriff.

dstHandle =  OpenSqlFilestream(dstFilePath, Write, 0,  
    transactionToken, cbTransactionToken, 0);  
  
//Write some date to the FILESTREAM BLOB.  
WriteFile(dstHandle, updateData, ...);  
  
//DDL statements will be denied.  
//DML statements will be denied.  
//SELECT statements will be allowed. The FILESTREAM BLOB is  
//returned without the modifications that are made by  
//WriteFile(dstHandle, updateData, ...).  
CloseHandle(dstHandle);  
  
//DDL statements will be allowed.  
//DML statements will be allowed.  
//SELECT statements will be allowed. The FILESTREAM BLOB  
//is returned with the updateData applied.  

B. Öffnen eines FILESTREAM-BLOB für lesezugriff

Das folgende Beispiel zeigt die Auswirkung des Öffnens einer Datei nur für lesezugriff.

dstHandle =  OpenSqlFilestream(dstFilePath, Read, 0,  
    transactionToken, cbTransactionToken, 0);  
//DDL statements will be denied.  
//DML statements will be allowed. Any changes that are  
//made to the FILESTREAM BLOB will not be returned until  
//the dstHandle is closed.  
//SELECT statements will be allowed.  
CloseHandle(dstHandle);  
  
//DDL statements will be allowed.  
//DML statements will be allowed.  
//SELECT statements will be allowed.  

C. Öffnen und Schließen mehrerer FILESTREAM-BLOB-Dateien

Wenn mehrere Dateien geöffnet sind, wird die restriktivste Regel verwendet. Im folgenden Beispiel werden zwei Dateien geöffnet. Die erste Datei wird zum Lesen und zum zweiten zum Schreiben geöffnet. DML-Anweisungen werden verweigert, bis die zweite Datei geöffnet wird.

dstHandle =  OpenSqlFilestream(dstFilePath, Read, 0,  
    transactionToken, cbTransactionToken, 0);  
//DDL statements will be denied.  
//DML statements will be allowed.  
//SELECT statements will be allowed.  
  
dstHandle1 =  OpenSqlFilestream(dstFilePath1, Write, 0,  
    transactionToken, cbTransactionToken, 0);  
  
//DDL statements will be denied.  
//DML statements will be denied.  
//SELECT statements will be allowed.  
  
//Close the read handle. The write handle is still open.  
CloseHandle(dstHandle);  
//DML statements are still denied because the write handle is open.  
  
//DDL statements will be denied.  
//DML statements will be denied.  
//SELECT statements will be allowed.  
  
CloseHandle(dstHandle1);  
//DDL statements will be allowed.  
//DML statements will be allowed.  
//SELECT statements will be allowed.  

D. Fehler beim Schließen eines Cursors

Das folgende Beispiel zeigt, wie ein nicht geschlossener Anweisungscursor verhindern OpenSqlFilestream() kann, dass das BLOB für den Schreibzugriff geöffnet wird.

TCHAR *sqlDBQuery =  
TEXT("SELECT GET_FILESTREAM_TRANSACTION_CONTEXT(),")  
TEXT("Chart.PathName() FROM Archive.dbo.Records");  
  
//Execute a long-running Transact-SQL statement. Do not allow  
//the statement to complete before trying to  
//open the file.  
  
SQLExecDirect(hstmt, sqlDBQuery, SQL_NTS);  
  
//Before you call OpenSqlFilestream() any open files  
//that the Cursor the Transact-SQL statement is using  
// must be closed. In this example,  
//SQLCloseCursor(hstmt) is not called so that  
//the transaction will indicate that there is a file  
//open for reading. This will cause the call to  
//OpenSqlFilestream() to fail because the file is  
//still open.  
  
HANDLE srcHandle =  OpenSqlFilestream(srcFilePath,  
     Write, 0,  transactionToken,  cbTransactionToken,  0);  
  
//srcHandle will == INVALID_HANDLE_VALUE because the  
//cursor is still open.  

Siehe auch

Zugreifen auf FILESTREAM-Daten mit OpenSqlFilestream
Verwenden von Multiple Active Result Sets (MARS)