带进度的SQL Server FileStream存取

原创 2015年12月08日 13:42:17

SQL Server FileStream 功能的详细参考联机帮助设计和实现 FILESTREAM 存储
这里只是把使用 Win32 管理 FILESTREAM 数据的代码调整了一下,实现带进度的存取,这对于存取较大的文件比较有意义
要使用FileStream,首先要在 SQL Server配置管理器中打开FileStream选项:SQL Server配置管理器–SQL Server服务–右边的服务列表中找到SQL Server服务–属性–FILESTREAM–允许远程客户端访问FILESTREAM数据根据需要选择,其他两荐都选上。配置完成后,需要重新启动SQL Server服务使设置生效。
然后使用下面的脚本创建测试数据库和测试表

 -- =========================================================
-- 启用 filestream_access_level
-- =========================================================
EXEC sp_configure 'filestream_access_level', 2;     -- 0=禁用  1=针对 T-SQL 访问启用 FILESTREAM  2=针对 T-SQL 和 WIN32 流访问启用 FILESTREAM
RECONFIGURE;
GO

-- =========================================================
-- 创建测试数据库
-- =========================================================
EXEC master..xp_create_subdir 'f:\temp\db\_test';
CREATE DATABASE _test
ON
    PRIMARY(
        NAME = _test, FILENAME = 'f:\temp\db\_test\_test.mdf'),
    FILEGROUP FG_stream CONTAINS FILESTREAM(
        NAME = _test_file_stream, FILENAME = 'f:\temp\db\_test\stream')
    LOG ON(
        NAME = _test_log, FILENAME = 'f:\temp\db\_test\_test.ldf')
;
GO

-- =========================================================
-- FileStream
-- =========================================================
-- =================================================
-- 创建 包含 FileStream 数据的表
-- -------------------------------------------------
CREATE TABLE _test.dbo.tb_fs(
    id uniqueidentifier ROWGUIDCOL      -- 必需
        DEFAULT NEWSEQUENTIALID ( ) PRIMARY KEY,
    name nvarchar(260),
    content varbinary(max) FILESTREAM
);
GO
下面的 VB 脚本实现带进度显示的文件存(Write方法)取(Read方法)
Imports System.IO
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes

Module Module1
    Public Sub Main(ByVal args As String())
        Dim sqlConnection As New SqlConnection("Integrated Security=true;server=localhost")
        Try
            sqlConnection.Open()
            Console.WriteLine("将文件保存到 FileStream")
            Write(sqlConnection, "test", "f:\temp\re.csv")
            Console.WriteLine("从 FileStream 读取数据保存到文件")
            Read(sqlConnection, "test", "f:\temp\re_1.csv")
        Catch ex As System.Exception
            Console.WriteLine(ex.ToString())
        Finally
            sqlConnection.Close()
        End Try

        Console.WriteLine("处理结束,按 Enter 退出")
        Console.ReadLine()
    End Sub

    ''' <summary>
    ''' 将文件保存到数据库
    ''' </summary>
    ''' <param name="conn">数据库连接</param>
    ''' <param name="name">名称</param>
    ''' <param name="file">文件名</param>
    Sub Write(ByVal conn As SqlConnection, ByVal name As String, ByVal file As String)
        Dim bufferSize As Int32 = 1024

        Using sqlCmd As New SqlCommand
            sqlCmd.Connection = conn
            '事务
            Dim transaction As SqlTransaction = conn.BeginTransaction("mainTranaction")
            sqlCmd.Transaction = transaction

            '1. 读取 FILESTREAM 文件路径 ( 注意函数大小写 )
            sqlCmd.CommandText = "
UPDATE _test.dbo.tb_fs SET content = 0x WHERE name = @name;
IF @@ROWCOUNT = 0 INSERT _test.dbo.tb_fs(name, content) VALUES( @name, 0x );
SELECT content.PathName() FROM _test.dbo.tb_fs WHERE name = @name;"
            sqlCmd.Parameters.Add(New SqlParameter("name", name))
            Dim filePath As String = Nothing
            Dim pathObj As Object = sqlCmd.ExecuteScalar()
            If Not pathObj.Equals(DBNull.Value) Then
                filePath = DirectCast(pathObj, String)
            Else
                Throw New System.Exception("content.PathName() failed to read the path name for the content column.")
            End If

            '2. 读取当前事务上下文
            sqlCmd.CommandText = "SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()"
            Dim obj As Object = sqlCmd.ExecuteScalar()
            Dim txContext As Byte() = Nothing
            Dim contextLength As UInteger
            If Not obj.Equals(DBNull.Value) Then
                txContext = DirectCast(obj, Byte())
                contextLength = txContext.Length()
            Else
                Dim message As String = "GET_FILESTREAM_TRANSACTION_CONTEXT() failed"
                Throw New System.Exception(message)
            End If

            '3. 获取 Win32 句柄,并使用该句柄在 FILESTREAM BLOB 中读取和写入数据
            Using sqlFileStream As New SqlFileStream(filePath, txContext, FileAccess.Write)
                Dim buffer As Byte() = New Byte(bufferSize - 1) {}
                Dim numBytes As Integer = 0
                Using fsRead As New FileStream(file, FileMode.Open)
                    While True
                        numBytes = fsRead.Read(buffer, 0, bufferSize)
                        If numBytes = 0 Then Exit While
                        sqlFileStream.Write(buffer, 0, numBytes)
                        Console.WriteLine(String.Format("{0} -> {1} -> {2}", fsRead.Position, sqlFileStream.Position, numBytes))
                    End While
                    fsRead.Close()
                End Using
                sqlFileStream.Close()
            End Using
            sqlCmd.Transaction.Commit()
        End Using
    End Sub

    ''' <summary>
    ''' 从数据库读取数据保存到文件
    ''' </summary>
    ''' <param name="conn">数据库连接</param>
    ''' <param name="name">名称</param>
    ''' <param name="file">文件名</param>
    Sub Read(ByVal conn As SqlConnection, ByVal name As String, ByVal file As String)
        Dim bufferSize As Int32 = 1024

        Using sqlCmd As New SqlCommand
            sqlCmd.Connection = conn

            '1. 读取 FILESTREAM 文件路径 ( 注意函数大小写 )
            sqlCmd.CommandText = "SELECT content.PathName() FROM _test.dbo.tb_fs WHERE name = @name;"
            sqlCmd.Parameters.Add(New SqlParameter("name", name))
            Dim filePath As String = Nothing
            Dim pathObj As Object = sqlCmd.ExecuteScalar()
            If Not pathObj.Equals(DBNull.Value) Then
                filePath = DirectCast(pathObj, String)
            Else
                Throw New System.Exception("content.PathName() failed to read the path name for the content column.")
            End If

            '2. 读取当前事务上下文
            Dim transaction As SqlTransaction = conn.BeginTransaction("mainTranaction")
            sqlCmd.Transaction = transaction
            sqlCmd.CommandText = "SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()"
            Dim obj As Object = sqlCmd.ExecuteScalar()
            Dim txContext As Byte() = Nothing
            Dim contextLength As UInteger
            If Not obj.Equals(DBNull.Value) Then
                txContext = DirectCast(obj, Byte())
                contextLength = txContext.Length()
            Else
                Dim message As String = "GET_FILESTREAM_TRANSACTION_CONTEXT() failed"
                Throw New System.Exception(message)
            End If

            '3. 获取 Win32 句柄,并使用该句柄在 FILESTREAM BLOB 中读取和写入数据
            Using sqlFileStream As New SqlFileStream(filePath, txContext, FileAccess.Read)
                Dim buffer As Byte() = New Byte(bufferSize - 1) {}
                Dim numBytes As Integer = 0
                Using fsRead As New FileStream(file, FileMode.Create)
                    While True
                        numBytes = sqlFileStream.Read(buffer, 0, bufferSize)
                        If numBytes = 0 Then Exit While
                        fsRead.Write(buffer, 0, numBytes)
                        Console.WriteLine(String.Format("{0} -> {1} -> {2}", sqlFileStream.Position, sqlFileStream.Position, numBytes))
                    End While
                    fsRead.Close()
                End Using
                sqlFileStream.Close()
            End Using
            sqlCmd.Transaction.Commit()
        End Using
    End Sub
End Module

SQLServer 2008 FileStream简单实例

1.打开服务,内置账户为 local system。(其它不行) 2.选择选项FileStream,勾选以下。然后重启服务 3.打开management studio,右键服务—属性。...
  • kk185800961
  • kk185800961
  • 2013年08月27日 13:34
  • 2766

在SQL Server 中启用 FileStream

最近在研究在数据库中存储大数据文件,看到了FileStream 这个功能,记录下来以备后用 FileStream 一般在安装的时候默认是不启用的,如果你留意的话,在选择数据库文件路径那个窗口,有一个...
  • zhnglicho
  • zhnglicho
  • 2013年09月02日 23:51
  • 4706

如何在SQL Server上Enable Filestream以及创建一个支持File Stream的DB?

博客地址:http://blog.csdn.net/shelleyliu0415   如果你想使用FileStream,必须先在SQL Server Management里Enable Fil...
  • ShelleyLiu0415
  • ShelleyLiu0415
  • 2015年11月24日 15:30
  • 1019

Sqlserver2008 2012配置文件流数据库FileStream

SQL Server 2008推出了一个新的特性叫做文件流(FILESTREAM),它使得基于SQL Server的应用程序可以在文件系统中存储非结构化的数据,例如文档、图片、音频、视频等等。文件流主...
  • angle860123
  • angle860123
  • 2014年05月07日 14:30
  • 2062

解决SQLSERVER在还原数据时出现的“FILESTREAM功能被禁用”问题

解决SQLSERVER在还原数据时出现的“FILESTREAM功能被禁用”问题 今天由于测试需要,在网上下载了Adventureworks2008实例数据库的BAK文件,进行还原时出现了这样的错误...
  • dyllove98
  • dyllove98
  • 2013年07月27日 20:09
  • 2426

SQL Server 2012新特性(1)T-SQL操作FileTable目录实例

在SQL Server 2008提供FileStream,以借助Windows系统本身的API来强化SQL Server对于非结构化数据的支持后,SQL Server 2012更是推出了像Contai...
  • downmoon
  • downmoon
  • 2014年04月23日 17:04
  • 7400

FileStream类的一些用法

FileStream读取文件的基本语法和方法
  • u010452388
  • u010452388
  • 2016年05月22日 10:22
  • 3383

在SQL Server 中启用 FileStream

最近在研究在数据库中存储大数据文件,看到了FileStream 这个功能,记录下来以备后用 FileStream 一般在安装的时候默认是不启用的,如果你留意的话,在选择数据库文件路径那个窗口,有一个...
  • zhnglicho
  • zhnglicho
  • 2013年09月02日 23:51
  • 4706

如何在SQL Server上Enable Filestream以及创建一个支持File Stream的DB?

博客地址:http://blog.csdn.net/shelleyliu0415   如果你想使用FileStream,必须先在SQL Server Management里Enable Fil...
  • ShelleyLiu0415
  • ShelleyLiu0415
  • 2015年11月24日 15:30
  • 1019

SQL Server 2008中使用FileStream存取大文件

SQL Server 2008中引入了Filestream,使用它可以将非机构化大型数据(如文本文档、图像和视频)等以varbinary(max)的形式存储在文件系统中。使用数据库的备份还原功能可以将...
  • babyan
  • babyan
  • 2011年08月26日 15:43
  • 1789
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:带进度的SQL Server FileStream存取
举报原因:
原因补充:

(最多只允许输入30个字)