Транзакционные CloudBlobs - PullRequest
4 голосов
/ 29 июля 2011

Я использую SQL Azure для хранилища метаданных BLOB-объектов и хранилища BLOB-объектов Azure для реальных BLOB-объектов.Создание / удаление BLOB-объектов осуществляется путем включения этих операций в окружающий TransactionScope.Пока все работает нормально, но мне интересно, может ли кто-нибудь порекомендовать оптимизацию операции удаления (см. Исходный код ниже), которая может избавить от необходимости загружать содержимое BLOB-объектов для отката.

public class CloudBlobDeletionEnlistment : CloudBlobBaseEnlistment,
  IEnlistmentNotification,
  IDisposable
{
  public CloudBlobDeletionEnlistment(Guid ownerId, string blobId, CloudBlobContainer container, Logger logger, IUserUploadActivity currentUploadActivity)
  {
    ctx = new Context { OwnerId = ownerId, BlobId = blobId, Container = container, Logger = logger, CurrentUploadActivity = currentUploadActivity };
  }

  public ~CloudBlobDeletionEnlistment()
  {
    Dispose(false);
  }

  public class Context
  {
    public Guid OwnerId;
    public string BlobId;
    public string ContentFileName;
    public string MimeType;
    public bool IsCompressed;
    public CloudBlobContainer Container;
    public Logger Logger;
    public IUserUploadActivity CurrentUploadActivity;
  }

  private readonly Context ctx;
  private CloudBlob blob;

  public void Prepare(PreparingEnlistment preparingEnlistment)
  {
    blob = ctx.Container.GetBlobReference(ctx.BlobId);

    // save backup information
    ctx.ContentFileName = Path.GetTempFileName();
    blob.DownloadToFile(ctx.ContentFileName);
    blob.FetchAttributes();
    ctx.MimeType = blob.Metadata[Constants.BlobMetaAttributeContentType];
    ctx.IsCompressed = bool.Parse(blob.Metadata[Constants.BlobMetaAttributeCompressed]);

    // delete it
    blob.DeleteIfExists();

    // done
    preparingEnlistment.Prepared();
  }

  public void Commit(Enlistment enlistment)
  {
    Cleanup();

    // done
    enlistment.Done();
  }

  public void Rollback(Enlistment enlistment)
  {
    if (blob != null)
    {
      try
      {
        blob.UploadFile(ctx.ContentFileName);
        blob.Metadata[Constants.BlobMetaAttributeContentType] = ctx.MimeType;
        blob.Metadata[Constants.BlobMetaAttributeCompressed] = ctx.IsCompressed.ToString();
        blob.SetMetadata();
      }

      finally
      {
        Cleanup();
      }
    }

    else Cleanup();

    // done
    enlistment.Done();
  }

  public void InDoubt(Enlistment enlistment)
  {
    Cleanup();

    enlistment.Done();
  }

  void Cleanup()
  {
    // delete the temporary file holding the blob content
    if (!string.IsNullOrEmpty(ctx.ContentFileName) && File.Exists(ctx.ContentFileName))
    {
      File.Delete(ctx.ContentFileName);
      ctx.ContentFileName = null;
    }
  }

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }

  protected virtual void Dispose(bool disposing)
  {
    if (disposing)
    {
      // free managed resources
    }

    // free native resources if there are any.
    Cleanup();
  }
  #endregion
}

Ответы [ 2 ]

1 голос
/ 29 июля 2011

Мне это не кажется безопасным механизмом отката - загрузка может завершиться неудачно, и если это произойдет, ваша согласованность данных будет нарушена.

Что делать, если вы удалите свои большие двоичные объекты, поместив их именаToBeDeleted таблица в базе данных - а затем вы настраиваете какое-то обычное задание, время от времени удаляя эти BLOB-объекты?

0 голосов
/ 30 июля 2011

Мне кажется, что вы хотите создать большой двоичный объект и создать метаданные в контексте одной транзакции.Это невозможно.Ваша логика программы должна быть «транзакцией».

То же самое относится и к логике удаления.

...