.Net C# VB.Ner SQLServerのバックアップをクライアントで保存

.NetでSQLServerのバックアップをクライアントで保存する方法です。

SQLServerでバックアップを行うと、SQLServerがインストールされているサーバー上にバックアップが作られます。
それを、クライアント側に移動させたいのですが、
Windowsのファイル共有を使うことができない場合の方法です。

まず、通常通りバックアップを行います。
次に、SQLServerに一時テーブルを作成し、そこにバックアップしたものを Insert します。
それを Select し、クライアント側でファイルとして保存します。

VB.Net の場合

Dim guid As String = System.Guid.NewGuid().ToString("N")
Dim backUpFileName As String = $"C:\backupFolder\{My.Settings.DataBaseName_{DateTime.Now.ToShortDateString.Replace("/", "")}_{Left(guid, 15)}.bak"

Try
    Using con As New SqlConnection(conectionStrings)

        con.Open()

        Dim cmd As New SqlCommand()
        cmd.Connection = con

        cmd.CommandText = $"BACKUP DATABASE [{My.Settings.DataBaseName}] TO  DISK = N'{backUpFileName}' WITH NOFORMAT, INIT,  NAME = N'{My.Settings.InstanceName名}-完全 データベース バックアップ'"
        cmd.ExecuteNonQuery()

        cmd.CommandText = $"IF OBJECT_ID('tempdb..##{guid}') IS NOT NULL DROP TABLE ##{guid}"
        cmd.ExecuteNonQuery()

        cmd.CommandText = $"CREATE TABLE ##{guid} (bck VARBINARY(MAX))"
        cmd.ExecuteNonQuery()

        cmd.CommandText = $"INSERT INTO ##{guid} SELECT bck.* FROM OPENROWSET(BULK '{backUpFileName}',SINGLE_BLOB) bck"
        cmd.ExecuteNonQuery()

        cmd.CommandText = $"select bck from ##{guid}"

        Using dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)

            If (dr.HasRows) Then

                dr.Read()

                Const constBufLength As Integer = 1024 * 1024 * 10 ' 10MByte
                Dim buf(constBufLength) As Byte
                Dim index As Integer = 0
                Dim readLength As Long = 1
                Dim ordinal As Integer = dr.GetOrdinal("bck")

                Using fs As New FileStream(argBuckupPath, FileMode.Create, FileAccess.Write)
                    Using bw As New BinaryWriter(fs)
                        While (readLength > 0)

                            readLength = dr.GetBytes(ordinal, index, buf, 0, constBufLength)
                            bw.Write(buf, 0, readLength)
                            bw.Flush()
                            index += readLength

                        End While
                    End Using
                End Using
            End If
        End Using
    End Using

Catch ex As Exception
    MsgBox(ex.Message, MessageBoxButtons.OK)
Finally
    Try
        ' 一時テーブル削除
        Using con As New SqlConnection(conectionStrings)
            Dim cmd As New SqlCommand()
            cmd.Connection = con
            cmd.CommandText = $"DROP TABLE ##{guid}"
            cmd.ExecuteNonQuery()
        End Using
    Catch ex As Exception
        ' 何もしない
    End Try
End Try