Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Las aplicaciones que usan SqlOpenFilestream() para abrir manejadores de archivos Win32 para leer o escribir datos BLOB FILESTREAM pueden encontrar errores de conflicto con instrucciones Transact-SQL que se administran en una transacción compartida. Esto incluye Transact-SQL o consultas de MARS que tardan mucho tiempo en finalizar la ejecución. Las aplicaciones deben diseñarse cuidadosamente para ayudar a evitar estos tipos de conflictos.
Cuando el motor de base de datos o las aplicaciones de SQL Server intentan abrir blobs FILESTREAM, el motor de base de datos comprueba el contexto de transacción asociado. El motor de base de datos permite o deniega la solicitud en función de si la operación abierta funciona con instrucciones DDL, instrucciones DML, recuperación de datos o administración de transacciones. En la tabla siguiente se muestra cómo determina el motor de base de datos si se permitirá o denegará una instrucción Transact-SQL en función del tipo de archivos abiertos en la transacción.
declaraciones Transact-SQL | Abierto para lectura | Abierto para escribir |
---|---|---|
Instrucciones DDL que funcionan con metadatos de base de datos, como CREATE TABLE, CREATE INDEX, DROP TABLE y ALTER TABLE. | Permitido | Se bloquean y fallan debido a un tiempo de espera. |
Instrucciones DML que funcionan con los datos almacenados en la base de datos, como UPDATE, DELETE e INSERT. | Permitido | Se deniega |
Seleccionar | Permitido | Permitido |
CONFIRMAR TRANSACCIÓN | Negado* | Negado*. |
GUARDAR TRANSACCIÓN | Negado* | Negado* |
REVERSIÓN | Permitido* | Permitido* |
* La transacción se cancela y se invalidan los identificadores abiertos para el contexto de transacción. La aplicación debe cerrar todos los identificadores abiertos.
Ejemplos
En los ejemplos siguientes, se muestra cómo las instrucciones Transact-SQL y el acceso de FILESTREAM Win32 pueden causar conflictos.
A. Apertura de un BLOB FILESTREAM para acceso de escritura
En el ejemplo siguiente se muestra el efecto de abrir un archivo solo para el acceso de escritura.
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. Abrir un BLOB de FILESTREAM para acceso de solo lectura
En el ejemplo siguiente se muestra el efecto de abrir un archivo solo para el acceso de lectura.
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. Apertura y cierre de varios archivos FILESTREAM BLOB
Si hay varios archivos abiertos, se usa la regla más restrictiva. En el ejemplo siguiente se abren dos archivos. El primer archivo se abre para lectura y el segundo para escritura. Las instrucciones DML serán denegadas hasta que se abra el segundo archivo.
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. No se puede cerrar un cursor
En el ejemplo siguiente se muestra cómo un cursor de instrucción que no está cerrado puede impedir OpenSqlFilestream()
que se abra el BLOB para el acceso de escritura.
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.
Véase también
Acceso a datos FILESTREAM con OpenSqlFilestream
Utilizar conjuntos de resultados activos múltiples (MARS)