Ich verwende SQL Azure für den Blob-Metadatenspeicher und Azure Blob Storage für die eigentlichen Blobs. Die Erstellung/Löschung von Blobs wird durch die Aufnahme dieser Vorgänge in das umgebende TransactionScope implementiert. Alles funktioniert so weit gut, aber ich frage mich, ob jemand Optimierungen für die Delete-Operation (siehe Quellcode unten) empfehlen kann, die die Anforderung zum Herunterladen der Blob-Inhalte, um Rollback loswerden könnte.
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
}