Azure SQL データベースのデータを DAC Framework を使ってエクスポートし、Azure Storage Services にアップロードするサンプルを書いてみた。バックアップだけでなく、バックアップ一覧の取得と、復旧も実装している。
エミューレータで動くことは確認したけど、本番環境で動くかどうかは確認してない。試用期間終わってまだ契約していないので、そもそも本番環境使えないんだけど。
バックアップ・復旧を行うためのクラスをメモしておく。実装したはいいけど、肝心のデータベースで DAC Framework がサポートしていない型(sql_variant)を使っているため、お蔵入りしそうだし。WorkerRole とかは省略。
using System; using System.Configuration; using System.IO; using System.Runtime.Serialization; using System.Linq; using Microsoft.SqlServer.Dac; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.StorageClient; namespace CloudBackupSample { /// <summary> /// DAC Framework でエクスポートしたバックアップパッケージを表します。 /// </summary> [DataContract] public class BackupPackage { /// <summary> /// <see cref="BackupPackages"/> /// クラスの新しいインスタンスを初期化します。 /// </summary> public BackupPackage() { } /// <summary> /// データベース名を取得または設定します。 /// </summary> [DataMember] public string DatabaseName { get; set; } /// <summary> /// URL を取得または設定します。 /// </summary> [DataMember] public Uri Uri { get; set; } } /// <summary> /// データベースのバックアップパッケージを作成しダウンロードする機能を適用します。 /// </summary> public class CloudBackup { /// <summary> /// Default 接続文字列を取得します。 /// </summary> private string ConnectionString { get { // 接続文字列名は適当なものに変更する // 外部から設定できるようにしてもいい。 return ConfigurationManager.ConnectionStrings["Default"].ConnectionString; } } /// <summary> /// 指定したデータベースをバックアップパッケージにエクスポートします。 /// </summary> /// <param name="databaseName">バックアップするデータベースの名前</param> /// <returns>作成したバックアップパッケージのパス</returns> private string ExportBackupPackage(string databaseName) { // 一時ファイルにエクスポート var packageFileName = Path.GetTempFileName(); var dac = new DacServices(ConnectionString); dac.ExportBacpac(packageFileName, databaseName); return packageFileName; } /// <summary> /// Windows Azure Storage Servics のアカウントを取得します。 /// </summary> private CloudStorageAccount CreateStorageAccount() { // 構成名は適当なものに変更する return CloudStorageAccount.FromConfigurationSetting("AzureStorageConnectionString"); } private string CreateContainerAddress() { // とりあえず backup 固定。 // 本番コードに組み込む場合はちゃんとしたアドレスを生成すること。 return "backup"; } private string CreateBlobAddressFromDatabaseName(string databaseName) { // データベース名にタイムスタンプを足す return databaseName + DateTime.UtcNow.Ticks; } /// <summary> /// メタデータのキーを定義します。 /// </summary> private class MetadataKey { public const string DATABASE_NAME = "DatabaseName"; } /// <summary> /// 指定したデータベースのバックアップパッケージを /// Azure Storage Service にエクスポートします。 /// </summary> /// <param name="databaseName">バックアップするデータベースの名前</param> public void ExportToCloudStorage(string databaseName) { // 一時ファイルにデータベースをエクスポート var packageFileName = ExportBackupPackage(databaseName); var account = CreateStorageAccount(); var blobClient = account.CreateCloudBlobClient(); // バックアップ用のコンテナを取得する var containerAddress = CreateContainerAddress(); var container = blobClient.GetContainerReference(containerAddress); container.CreateIfNotExist(); // コンテナが無ければ作成する // ブロブを取得する var blobAddress = CreateBlobAddressFromDatabaseName(databaseName); var blob = container.GetBlobReference(blobAddress); // パッケージをアップロード blob.UploadFile(packageFileName); // メタデータにデータベース名を設定する blob.Metadata.Add(MetadataKey.DATABASE_NAME, Uri.EscapeDataString(databaseName)); blob.SetMetadata(); // アップロードが完了したらパッケージを削除 File.Delete(packageFileName); } /// <summary> /// 指定したブロブ上のバックアップパッケージを使ってデータベースを復旧します。 /// </summary> /// <param name="databaseName">復旧先のデータベース名</param> /// <param name="blobAddress">バックアップパッケージの URL</param> public void ImportFromCloudStorage(string databaseName, string blobAddress) { var account = CreateStorageAccount(); var blobClient = account.CreateCloudBlobClient(); var blob = blobClient.GetBlobReference(blobAddress); // バックアップパッケージを Azure Storage Services から // 一時フォルダにダウンロード var packageFileName = Path.GetTempFileName(); blob.DownloadToFile(packageFileName); // DAC Framework を使ってインポート var package = BacPackage.Load(packageFileName); var dac = new DacServices(ConnectionString); dac.ImportBacpac(package, databaseName); // インポートが完了したらパッケージを削除 File.Delete(packageFileName); } /// <summary> /// Azure Storage Services に保存しているバックアップパッケージ一覧を取得します。 /// </summary> /// <returns>バックアップパッケージ一覧</returns> public BackupPackage[] FetchBackupPackagesFromCloudStorage() { var account = CreateStorageAccount(); var blobClient = account.CreateCloudBlobClient(); // コンテナを取得 var containerAddress = CreateContainerAddress(); var container = blobClient.GetContainerReference(containerAddress); container.CreateIfNotExist(); // ブロブを取得 return container.ListBlobs() .OfType<CloudBlob>() .Select(b => { b.FetchAttributes(); var dbName = Uri.UnescapeDataString(b.Metadata[MetadataKey.DATABASE_NAME]); return new BackupPackage() { DatabaseName = dbName, Uri = b.Uri, }; }) .ToArray(); } /// <summary> /// Azure Storage Services に保存しているバックアップパッケージを削除します。 /// </summary> /// <param name="blobAddress">削除するバックアップパッケージの URL</param> public void DeleteBackupPackage(string blobAddress) { var account = CreateStorageAccount(); var blobClient = account.CreateCloudBlobClient(); var blob = blobClient.GetBlobReference(blobAddress); blob.DeleteIfExists(); } } }