sexta-feira, 6 de novembro de 2009

Chave Duplicada no Azure Table Storage

Mais uma da série “Azure: Pense Numas Mensagenzinhas de Erro RUINS”. Como testar por tentativa de inserção de linhas duplicadas no Azure Table Storage?

Como o Azure é REST-based, as mensagens de erro tem que seguir a semântica REST (falei um pouco sobre isto em outro post). Então quando você tenta inserir uma linha com chave (PartitionKey e RowKey, mas como elas identificam unicamente uma linha, vou chamá-las só de chave) idêntica a outra que já está armazenada no Table Storage do Azure, ele retorna um erro HTTP 409. De acordo com a definição do protocolo HHTP no site do W3C,

10.4.10 409 Conflict
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request.

Bem, o “recurso” – a tabela no Azure – está em um “estado” – já existe uma linha com a chave igual à linha que estou tentando inserir – que conflita com o “pedido” – o INSERT da linha com chave duplicada. Realmente, como no caso do erro 404 quando não localizo uma linha procurando pela chave (o outro post citado acima), faz sentido “de um ponto de vista REST”. Mas de novo, se estou incluindo uma linha em uma tabela, esperaria algo do tipo “Chave primária duplicada”, e não “HTTP 409 – Conflict”.

Mas como dizem aqui no cerrado, “Whatever”. O try/catch para interceptar esse erro é:

contexto.AddObject("Usuarios", novoUsuario);

try

{
contexto.SaveChanges();
}
catch (System.Data.Services.Client.DataServiceRequestException erro)
{
// DataServiceRequestException é só um wrapper para o "erro de verdade",
// que fica em DataServiceRequestException.InnerException
System.Data.Services.Client.DataServiceClientException erroMesmo =
erro.InnerException as System.Data.Services.Client.DataServiceClientException;
if ((erroMesmo != null) && (erroMesmo.StatusCode == 409))
{
// HTTP status code 409: Conflict. Na criação de uma nova linha em uma tabela
// do Table Storage do Azure, se a linha sendo incluída tem Partition Key e
// Row Key identicas a uma linha já existente, é retornado o erro 409.
throw new Exception(string.Format("Já existe uma linha com a chave ({0},{1})",
novoUsuario.PartitionKey, novoUsuario.RowKey));
}
else
throw; // Outro erro – joga a batata quente pra cima
}