Evitar conflitos com operações de banco de dados em aplicativos de FILESTREAM

Os aplicativos que usam SqlOpenFilestream() para abrir identificadores de arquivo do Win32 para ler ou gravar dados BLOB FILESTREAM podem encontrar erros de conflito com instruções Transact-SQL gerenciadas em uma transação em comum. Isto inclui Transact-SQL ou a consultas MARS que levam muito tempo para concluir a execução. Aplicativos devem ser criados com cuidado para ajudar a evitar esses tipos de conflitos.

Quando o Mecanismo de Banco de Dados do SQL Server ou aplicativos tentam abrir BLOBs FILESTREAM, o Mecanismo de Banco de Dados verifica o contexto de transação associado. O Mecanismo de Banco de Dados permite ou nega a solicitação com base no fato de a operação aberta estar funcionando com instruções DDL, instruções DML, dados de recuperação ou transações de gerenciamento. A tabela a seguir mostra como o Mecanismo de Banco de Dados determina se uma instrução Transact-SQL será permitida ou negará com base no tipo de arquivos que estão abertos na transação.

instruções Transact-SQL

Abertas para leitura

Abertas para gravação

Instruções de DDL que funcionam com metadados de banco de dados, como CREATE TABLE, CREATE INDEX, DROP TABLE e ALTER TABLE.

Permitido

São bloqueadas e falham devido ao tempo limite esgotado.

Instruções DML que funcionam com os dados armazenados no banco de dados, como UPDATE, DELETE e INSERT.

Permitido

Negadas

SELECT

Permitido

Permitido

COMMIT TRANSACTION

Negadas*

Negadas*.

SAVE TRANSACTION

Negadas*

Negadas*

ROLLBACK

Permitidas*

Permitidas*

* A transação é cancelada e os identificadores abertos para o contexto da transação são invalidados. O aplicativo deve fechar todos os identificadores abertos.

Exemplos

Os exemplos a seguir mostram como as instruções Transact-SQL e acesso de FILESTREAM Win32 podem causar conflitos.

A.Abrindo um BLOB FILESTREAM para acesso de gravação

O exemplo a seguir mostra o efeito de abrir um arquivo para acesso apenas de gravação.

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.Abrindo um BLOB FILESTREAM para acesso de leitura

O exemplo a seguir mostra o efeito de abrir um arquivo para acesso apenas de leitura.

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.Abrindo e fechando vários arquivos de BLOB FILESTREAM

Se vários arquivos estiverem abertos, será usada a regra mais restritiva. O exemplo a seguir abre dois arquivos. O primeiro é aberto para leitura e o segundo, para gravação. As instruções DML serão negadas até que o segundo arquivo seja aberto.

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.Falha ao fechar um cursor

O exemplo a seguir mostra como um cursor de instrução que não está fechado pode impedir OpenSqlFilestream() de abrir o BLOB para acesso de gravação.

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.

Consulte também

Referência

Acessar dados do FILESTREAM com OpenSqlFilestream

Conceitos

Usando MARS (vários conjuntos de resultados ativos)