segunda-feira, 23 de janeiro de 2012

Haja Produtividade

Quando for fazer um projeto pra nuvem, lembre-se de acrescentar no cronograma uma gordurinha extra por conta dos deploys da aplicação. Olha um log de deploy de um projeto Cloud no VS2010:


16:22:27 - Warning: There are package validation warnings.
16:22:28 - Preparing...
16:22:28 - Connecting...
16:22:31 - Uploading...
16:30:31 - Creating...
16:31:41 - Starting...
16:32:16 - Initializing...
16:32:16 - Instance 0 of role _____________ is initializing
16:32:16 - Instance 0 of role _____________ is initializing
16:36:12 - Instance 0 of role _____________ is busy
16:36:12 - Instance 0 of role _____________ is busy
16:37:19 - Instance 0 of role _____________ is ready
16:37:52 - Instance 0 of role _____________ is ready
16:37:54 - Complete.

16:22 pra 16:37... só 15 minutos esperando o deploy :-P Tá me lembrando a época da bolsa de computação gráfica da UnB, que a gente mandava compilar o aplicativo e demorava 5 minutos. Aí testava, corrigia alguma coisa e mais 5 minutos pra compilar. Haja produtividade ;-)

sexta-feira, 20 de janeiro de 2012

"Unable to load the specified metadata resource", ou "Como perder 2 dias por causa de um asterisco"

Mais uma pra pilha "Azure - Mais Um Detalhe De Desenvolvimento". Resolvemos migrar as tabelas de uma aplicação Azure do ATS para o SQL Azure.
OBS1: Se você vai começar seu projeto agora, *não* use o ATS como um banco relacional. A lista de problemas é tão grande que não vou nem colocar aqui.
Bem, fizemos os testes locais e tudo rodou tranquilo.
OBS2: Conselho para desenvolvimento no Azure: "Não escreve muito código sem um deploy e teste na nuvem". Os Compute/Storage Emulators e a nuvem tem vários comportamentos e particularidades diferentes entre si. Desenvolva um trecho, estabilize o suficiente para um teste, e faça um deploy na nuvem para teste lá. Obrigado ao Vitor por emprestar a frase.
Na hora que passamos para a nuvem, no primeiro acesso ao BD no SQL Azure, aparecia uma exceção "Unable to load the specified metada". Resumindo (muito), a estória é a seguinte:

  1. Nossa camada de dados é uma DLL separada (AcessoDados.dll), que contém um modelo Entity Framework apontando para o BD no SQL Azure, e mais um tanto de código customizado.
  2. A aplicação tem um web role e um worker role. Esta DLL é referenciada por ambos, já que ambos manipulam as mesmas tabelas.
  3. A string de conexão ao modelo EF começa assim:
    connectionString="metadata=res://*/Entidades.BDAplicacao.csdl|res://*/Entidades. BDAplicacao .ssdl|res://*/Entidades.BDAplicacao.msl; ...". Estes arquivos são necessários para o Entity Framework realizar o acesso ao banco de dados representado pelo modelo.
  4. O modelo EF tem uma propriedade chamada "Metadata Artifact Processing", que por default vale "Embed in Output Assembly". Isto significa que os 3 arquivos na string de conexão (BDAplicacao.csdl, BDAplicacao.ssdl e BDAplicacao.msl) são incorporados à DLL como recursos durante a compilação.
A mensagem de erro indicava que, na hora que o worker role ia acessa o banco, não encontrava os 3 arquivos necessários para a geração dos comandos de acesso ao banco. Então a exceção "Unable to load the specified metadata resource" ocorria.

A string de conexão no item 3 acima é a string padrão gerado pelo Designer de Modelos Entity Framework do Visual Studio 2010. Basicamente, os asteriscos na string de conexão significam "procure estes arquivos nos recursos de todos os assemblies carregados no momento". Não sei exatamente porque, mas o fato é que o worker role, quando rodando na nuvem, não encontrava os arquivos dentro da DLL (quando rodando no Compute Emulator, tudo funcionava ok). Tivemos então que especificar o nome da DLL em vez dos asteriscos, e a aplicação passou a funcionar também na nuvem. A string de conexão ficou assim:

connectionString="metadata=res://AcessoDados/Entidades.BDAplicacao.csdl|res:// AcessoDados /Entidades. BDAplicacao .ssdl|res://AcessoDados/Entidades.BDAplicacao.msl; ...".

Mais alguns detalhes pra fechar:
  • Repare que colocamos o nome da DLL, mas não sua extensão. Caso você coloque a extensão, será gerada uma exceção "Não foi possível localizar o arquivo ...".
  • O modelo EF se chama "BDAplicacao", e está dentro de um sub-namespace "Entidades". Então veja que o nome dos arquivos não é simplemente o nome do modelo com as extensões .csdl, .ssdl e .msl; o nome dos arquivos é "Entidades.BDAplicacao"; tem que ser acrescentado o namespace ao nome dos arquivos, exceto pela parte "raiz" do namespace - que é o nome da DLL.
E aí? Pouco detalhe, né não?