SqlOpenFilestream() を使用して WIN32 ファイル ハンドルを開き、FILESTREAM BLOB データの読み取りまたは書き込みを行うアプリケーションでは、一般的なトランザクションで管理されている Transact-SQL ステートメントとの競合エラーが発生する可能性があります。 これには、実行の完了に長い時間がかかる Transact-SQL または MARS クエリが含まれます。 これらの種類の競合を回避するために、アプリケーションは慎重に設計する必要があります。
SQL Server データベース エンジンまたはアプリケーションが FILESTREAM BLOB を開こうとすると、データベース エンジンは関連するトランザクション コンテキストをチェックします。 データベース エンジンは、開いている操作が DDL ステートメント、DML ステートメント、データの取得、トランザクションの管理のいずれで動作しているかに基づいて、要求を許可または拒否します。 次の表は、トランザクションで開かれているファイルの種類に基づいて、Transact-SQL ステートメントを許可または拒否するかどうかをデータベース エンジンが決定する方法を示しています。
Transact-SQL ステートメント | 読み取り用に開く | 書き込み用に開く |
---|---|---|
CREATE TABLE、CREATE INDEX、DROP TABLE、ALTER TABLE などのデータベース メタデータを操作する DDL ステートメント。 | 許可 | ブロックされ、タイムアウトで失敗します。 |
UPDATE、DELETE、INSERT など、データベースに格納されているデータを操作する DML ステートメント。 | 許可 | 拒否する |
選択する | 許可 | 許可 |
トランザクションをコミット | 拒否* | 拒否*。 |
トランザクションの保存 | 拒否* | 拒否* |
ロールバック | 許可* | 許可* |
* トランザクションが取り消され、トランザクション コンテキストのオープン ハンドルが無効になります。 アプリケーションは、開いているすべてのハンドルを閉じる必要があります。
例示
次の例は、Transact-SQL ステートメントと FILESTREAM Win32 アクセスが競合を引き起こす可能性のある方法を示しています。
ある。 書き込みアクセス用に FILESTREAM BLOB を開く
次の例は、書き込みアクセス専用にファイルを開く効果を示しています。
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. 読み取りアクセス用に FILESTREAM BLOB を開く
次の例は、読み取りアクセス専用でファイルを開く効果を示しています。
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. 複数の FILESTREAM BLOB ファイルを開いたり閉じたりする
複数のファイルが開いている場合は、最も制限の厳しい規則が使用されます。 次の例では、2 つのファイルを開きます。 最初のファイルは読み取り用に開き、2 番目のファイルは書き込み用に開かれます。 DML ステートメントは、2 番目のファイルが開かれるまで拒否されます。
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. カーソルを閉じられなかった
次の例は、閉じていないステートメント カーソルによって、 OpenSqlFilestream()
が書き込みアクセスのために BLOB を開けないようにする方法を示しています。
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.
こちらもご覧ください
OpenSqlFilestream を使用して FILESTREAM データにアクセスする
複数のアクティブな結果セット (MARS) の使用