quarta-feira, 22 de junho de 2011

Contando e apagando linhas no Azure Storage Emulator

Eu *sei* que a gente não deve fazer isto. Estamos importando lotes relativamente grandes de linhas para tabelas dentro do Storage Emulator do Azure. Durante os testes, várias vezes temos que contar as linhas importadas durante a execução da importação, e apagar as linhas das tabelas entre os testes. O certo seria fazer isto usando a API de acesso ao Azure Table Storage (ATS), mas é lento e tem que lidar com o tal do continuation token toda vez que a tabela tem mais de 1.000 linhas. Então criei uma função e uma procedure no banco do Storage Emulator pra facilitar minha vida.

O que a gente não deve fazer é acessar diretamente o BD do Storage Emulator. Ele é um BD simples, mas é sempre não-recomendado acessar as estruturas internas de qualquer ferramenta, pois elas podem mudar de uma versão pra outra, e aí seus "caminhos alternativos" (também conhecidos como "bacalhaus") páram de funcionar.

Todas as "tabelas" que você cria no Storage Emulator são guardadas na verdade em uma única tabela chamada "TableRow" no banco instalado pelo Storage Emulator. Este banco deve ter um padrão de nomenclatura, na minha máquina o nome dele é "DevelopmentStorageDb20090919". Ou é o dia da release do SDK do Azure, ou é o dia que uma filha minha quebrou o braço - ultimamente parece que eu vivo no hospital consertando essas criaturas.

Bem, a estrutura da tabela é:

CREATE TABLE [dbo].[TableRow](
   [AccountName] [varchar](24) NOT NULL,
   [TableName] [varchar](63) NOT NULL,
   [PartitionKey] [nvarchar](256) NOT NULL,
   [RowKey] [nvarchar](256) NOT NULL,
   [Timestamp] [datetime] NOT NULL,
   [Data] [xml] NULL,
)

A coluna TableName define a que "tabela" do ATS a linha pertence, PartitionKey e RowKey você já sabe o que é senão provavelmente não estaria lendo esse post, e Data (veja o tipo: xml) contém uma "tripa" XML com os valores para cada coluna da tabela.

Aí fica fácil. A função pra contar linhas de uma tabela do ATS é:

CREATE FUNCTION NumeroLinhas(@nomeTabela varchar(200))
RETURNS int
AS
BEGIN
 RETURN (SELECT COUNT(*) FROM TableRow (NOLOCK) WHERE TableName = @nomeTabela)
END
GO

A procedure para apagar os registros de uma tabela é:

CREATE PROC ApagaRegistros(@nomeTabela varchar(200))
AS
 DELETE FROM TableRow WHERE TableName = @nomeTabela
GO

Agora você pode contar as linhas de uma tabela no Storage Emulator executando

SELECT dbo.NumeroLinhas('Produtos')

e apagar as linhas desta tabela com

ApagaRegistros 'Produtos'

Bem mais rápido que fazer pela API. Claro que "só faça isso em casa": no seu ambiente de testes.



PS: Não é um cenário comum, mas as funções não levam em conta quando há mais de uma conta registrada. Para estes casos, o "WHERE" na função e na procedure devem fazer referência também à coluna "AccountName", para que seja especificada a conta na qual as operações devem ser feitas.