SqlFileStream
Avec l'arrivée du Framework 3.5 SP1 béta, de nouvelles classes ont fait leur apparition.
Notamment un ensemble de classes pour gérer le nouveau type SQL SERVER 2008 : FILESTREAM.
Lors de mes différentes présentations sur le sujet, j'ai toujours du utiliser une classe encapsulant un appel à une dll C, que je ne présentais pas d'ailleurs :) en expliquant que "bientôt" nous aurions droit à de vrais classes managed pour gérer tout ça
Et bien, c'est le cas; le framework (3.5 SP1 béta) est là !
Maintenant, tout devient (relativement) simple 
D'abord le script de création d'une table contenant un type FILESTREAM :
-- 1. Enable FILESTREAM support
EXEC [sp_filestream_configure] @enable_level = 3;
-- 2. Create a database with a File Group that contains FILESTREAM
CREATE DATABASE FileManagement
ON
PRIMARY (
NAME = FileManagement_Primary,
FILENAME = 'c:\temp\data\FileManagement.mdf'),
FILEGROUP FileStreamGroup CONTAINS FILESTREAM (
NAME = FileManagement_FileGroup,
FILENAME = 'c:\temp\data\FileManagement')
LOG ON ( NAME = FileManagement_Log,
FILENAME = 'c:\temp\data\FileManagementLog.ldf')
GO
-- 3. Create a Table with FILESTREAM
CREATE TABLE [dbo].[Files]
(
FileID uniqueidentifier NOT NULL ROWGUIDCOL PRIMARY KEY,
FileContents varbinary(max) FILESTREAM DEFAULT(0x)
)
GO
En préambule, on crée une transaction (BIENSUR !)
SqlTransaction tx = conn.BeginTransaction();
J'insère dans ma table, contenant un filestream, une ligne (tout ça pour récupérer un contexte de transaction par la suite)
SqlCommand insertFileCommand = conn.CreateCommand();
insertFileCommand.Transaction = tx;
insertFileCommand.CommandText = "INSERT INTO Files (FileID) VALUES (@FileID)";
Guid newFileID = Guid.NewGuid();
insertFileCommand.Parameters.Add("@FileID", SqlDbType.UniqueIdentifier).Value = newFileID;
insertFileCommand.ExecuteNonQuery();
Je récupère le contexte de transaction :
SqlCommand getPathAndTokenCommand = conn.CreateCommand();
getPathAndTokenCommand.Transaction = tx;
getPathAndTokenCommand.CommandText = "SELECT FileContents.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM Files WHERE FileID = @FileID";
getPathAndTokenCommand.Parameters.Add("@FileID", SqlDbType.UniqueIdentifier).Value = newFileID;
SqlDataReader tokenReader = getPathAndTokenCommand.ExecuteReader(CommandBehavior.SingleRow);
tokenReader.Read();
SqlString filePathName = tokenReader.GetSqlString(0);
SqlBinary fileToken = tokenReader.GetSqlBinary(1);
tokenReader.Close();
Et maintenant j'utilise ce fameux nouveau type, comme un simple type FileStream (j'ouvre un flux, et j'écris dedans !)
FileStream inputFile = File.OpenRead("TextFile1.txt");
SqlFileStream sqlFile = new SqlFileStream(filePathName.Value, fileToken.Value, System.IO.FileAccess.Write);
byte[] buffer = new byte[512 * 1024]; // 512Kb
int bytesRead = inputFile.Read(buffer, 0, buffer.Length);
while (bytesRead > 0)
{
sqlFile.Write(buffer, 0, bytesRead);
bytesRead = inputFile.Read(buffer, 0, buffer.Length);
}
J'oublie pas de tout fermer hein ;)
sqlFile.Close();
inputFile.Close();
tx.Commit();
conn.Close();
Et voilà !
Bon FILESTREAM ! 