Skip to content

Exceptions and exception handling

Jussi Saarivirta edited this page Jul 25, 2020 · 12 revisions

The Exception model

To help the user to figure out what exactly went wrong and to help in taking corrective actions the Exception model tries to throw meaningful and detailed exceptions. Since there are multiple different batching modes and therefore different behavior and different ways for the operations to fail, there are multiple different Exception types. In addition to those, a few general Exception types exist.

General Exception types

System.ArgumentNullException

This exception will be thrown from the constructor if some required parameter is null.

AzureTableDataStoreConfigurationException

This exception is thrown from the constructor if something in the initialization phase fails.

AzureTableDataStoreEntityValidationException<TData>

This exception is thrown when entity validation fails in insert, replace or merge operations, batched and non-batched. The EntityValidationErrors property is a Dictionary<TData, List<string>> that has each entity with validation issues as key and the list of validation issues as value. So from there you can pick the ones that caused the issues.

Example:

var entity = new MyEntity()
{
    PartitionKey = "Secret Agents",
    RowKey = "James Bond\t007", // contains an illegal char, \t
};

store.UseClientSideValidation = true;

try 
{
    await store.InsertAsync(BatchingMode.None, entity);
}
catch(AzureTableDataStoreEntityValidationException<MyEntity> e)
{
    List<string> validationErrors = e.EntityValidationErrors[entity];
    // validationErrors[0] is "Row key contains illegal characters"
    // Do something...
}

AzureTableDataStoreInternalException

A generic exception, when no specific exception type fits the context. These are thrown for example in situations like failing to initialize a table or a blob container, failing to translate a LINQ query expression to a table query, invalid parameters, and generally from all methods before any table or blob operations have occurred.

The InternalException usually contains the actual source of the issue.

AzureTableDataStoreSingleOperationException<TData>

Represents a failure of a single operation. This is thrown from insert, replace, merge and delete operations when there's only one entity to process. The exception contains Entity property of type TData that holds the reference to the failing entity, and a list of blob operation exceptions, BlobOperationExceptions with type List<AzureTableDataStoreBlobOperationException<TData>> that holds any blob operation errors if there were any when processing this insert/merge/replace/delete. If the error wasn't a blob operation error, the InnerException usually holds the actual exception that caused the failure.

Example:

// Setting up a failure.
var explodingStream = new Mock<Stream>();
mockStream.Setup(s => s.CanRead).Returns(true);
mockStream.Setup(s => s.Seek(It.IsAny<long>(), It.IsAny<SeekOrigin>()))
    .Throws(new Exception("BOOM!")); // this will get called and throws
mockStream.Setup(s => s.Length).Returns(100);

var entity = new MyEntity()
{
    PartitionKey = "Secret Agents",
    RowKey = "James Bond 007",
    MyBlob = new LargeBlob("image.png", explodingStream.Object, "image/png")
};

try
{
    await store.InsertAsync(BatchingMode.None, entity);
}
catch(AzureTableDataStoreSingleOperationException<MyEntity> e)
{
    LargeBlob blob = e.BlobOperationExceptions[0].SourceBlob; // blob that caused the issue
    MyEntity ent = e.BlobOperationExceptions[0].SourceEntity; // the parent entity
    Exception ex = e.InnerException; // Exception "BOOM!"
}
Clone this wiki locally