Завантаження даних в filestream
У цій замітці ми коротко поговоримо про те, якими способами можна організувати імпорт / експорт файлу з файлової системи в поле filestream таблиці на SQL Server і назад.
Спосіб 3. OpenSqlFilestream API.
A first chance exception of type 'System.ComponentModel.Win32Exception' occurred in System.Data.dll
A .NET Framework error occurred during execution of user defined routine or aggregate 'FilestreamStuff':
System.ComponentModel.Win32Exception: The request is not supported
at System.Data.SqlTypes.SqlFileStream.OpenSqlFileStream (String path, Byte [] transactionContext, FileAccess access, FileOptions options, Int64 allocationSize)
at System.Data.SqlTypes.SqlFileStream..ctor (String path, Byte [] transactionContext, FileAccess access, FileOptions options, Int64 allocationSize)
at System.Data.SqlTypes.SqlFileStream..ctor (String path, Byte [] transactionContext, FileAccess access)
at UserDefinedProcedures.FilestreamStuff (SqlString tblName, SqlString fsFldName, SqlGuid rowId, SqlString strToInsert, SqlInt64 startPos, SqlInt64 numExistingCharsToSubstitute)
User transaction, if any, will be rolled back.
No rows affected.
(0 row (s) returned)
Спосіб 4. Нерекомендовані.
Незважаючи на сермяжную невитіюватість цього способу вдаватися до нього я б не рекомендував ні за яких обставин, тому що він а) використовує недокументірование можливості SQL Server, які можуть не підтримуватися в наступній версії, і б) діє в обхід виконавчого механізму SQL Server. Оскільки SQL Server нічого не знає про те, що ми за його спиною будемо хімічити, він не буде враховувати ці зміни і відображати їх в журналі транзакцій, що може привести до порушень транзакционной цілісності і втрати даних. «Протягне все ноги процесор, замкнуться доріжки на платі, на мишку крізь щілину дисковода поллється киплячий метал». Даний спосіб приводиться в суто академічних цілях для повноти картини і загального розвитку, але не для практичного застосування.
У файлстрімовского БЛОБ є метод PathName (). Щоб він працював, файлстрім як на рівні SQL Server, так і на рівні файлової системи повинен бути сконфігурен в положення 2 (див. Продовження поста "Введення в файлстрім"), тобто потрібно поставити обидві галки: не тільки Enable FILESTREAM for Transact-SQL access, але і Enable FILESTREAM for file I / O streaming access, як в SQL Server Configuration Manager, так і в св-вах SQL Server. А можна і не ставити, тому що цей метод не має нічого спільного з фізичним шляхом і ім'ям файлу, що містить поле файлстрім цього запису, в файлової системі. Він повертає псевдопуть, складений
\\<Имя компьютера>\ MSSQLSERVER \ v1 \<Имя базы>\<Имя схемы>\<Имя таблицы>\<Имя файлстримовского поля>\<гуид записи из поля rowguidcol>.
select stream.PathName () from Media
select stream.PhysicalPathName () from Media where $ rowguid = '01588060-47FD-425B-997A-96375885395A'
Все, що тепер залишається зробити, - скопіювати в нього цікавить файл. Параметри процедури ідентичні параметрам ReadFileToBlobField, см. Пред.пост "Імпорт / експорт блобовскіх полів в файли - CLR". Там же наводиться код контрольної функції CheckObjectsValidity.
// exec ReadFileToFSBlobField 'Media', 'stream', '01588060-47FD-425B-997A-96375885395A', 'c: \ Temp \ Book1.csv'
public static void ReadFileToFSBlobField (SqlString tblName, SqlString colName, SqlGuid guid, SqlString fileName)
if (! CheckObjectsValidity (tblName, colName)) return;
SqlConnection cnn = new SqlConnection ( "context connection = true"); cnn.Open ();
SqlCommand cmd = new SqlCommand ( "select" + colName.ToString () + ".PhysicalPathName () from" + tblName.ToString () + "where $ rowguid = @guid", cnn);
cmd.Parameters.Add (new SqlParameter ( "@ guid", guid));
string blobFileName = (string) cmd.ExecuteScalar ();
Дорога назад - з файлстрімовского файлу в вільний файл.
// exec WriteFSBlobFieldToFile 'Media', 'stream', '01588060-47FD-425B-997A-96375885395A', 'c: \ Temp \ Book2.csv'
public static void WriteFSBlobFieldToFile (SqlString tblName, SqlString colName, SqlGuid guid, SqlString fileName)
if (! CheckObjectsValidity (tblName, colName)) return;
SqlConnection cnn = new SqlConnection ( "context connection = true"); cnn.Open ();
SqlCommand cmd = new SqlCommand ( "select" + colName.ToString () + ".PhysicalPathName () from" + tblName.ToString () + "where $ rowguid = @guid", cnn);
cmd.Parameters.Add (new SqlParameter ( "@ guid", guid));
string blobFileName = (string) cmd.ExecuteScalar ();