1 Alterações

A versão 1.0.0.1 da ferramena CRUDMatrixGenerator possou por um processo de Code Refactory e possui as seguintes novas funcionalidades:

  • Detecção de queries executadas contra outros bancos de dados que não o atual.
  • Além de analisar Stored Procedure, a ferramente também analisará Views.
  • Inclusão da coluna Type, responsável por identificar o tipo de objeto analisado, Stored Procedure ou View.

Veja abaixo as ilustrações, respectivamente, do log gerado pela ferramenta e da visualização dos dados no Excel (após procedimento importação):


Log


Log

2 Instalador

O instalador está disponível no endereço CRUDMatrixGeneratorSetup_1.0.0.1.zip.

3 Código-fonte

Você pode baixar o código-fonte desta ferramenta no endereço CRUDMatrixGenerator_SourceCode_1.0.0.1.zip.

1 Objetivo

Decidi desenvolver a ferramenta CRUDMatrixGenerator quando vi um amigo fazendo um levantamento para mapear quais stored procedures de um determinado banco de dados referenciavam quais tabelas. O processo era bem manual e poderia ser bastante trabalhoso dependendo do número de objetos no banco de dados.

2 Demonstração

A utilização da ferramente é bem simples, basta executar o CRUDMatrixGenerator informando a string de conexão do banco de dados e o diretório onde o relatório deverá ser gravado, respectivamente, definidos pelos parâmetros -c e -o. Veja a ilustração abaixo:

De acordo com a execução ilustrada acima, um arquivo texto, cujo nome segue o formato [GUID].txt, é gravado no diretório C:\Temp. Veja a ilustração abaixo:

Em seguida, basta importar o arquivo para o Excel informando o como separador de colunas. Veja o resultado na ilustração abaxo:

3 Instalador

O instalador está disponível no endereço CRUDMatrixGeneratorSetup.zip e o script do banco de dados utilizado no exemplo está disponível em DatabaseScript.zip.

4 Código-fonte

Você pode baixar o código-fonte desta ferramenta no endereço
CRUDMatrixGeneratorSourceCode.zip
.

1 Requerimentos de sistema

O bug relacionado neste post foi detectado utilizando-se os softwares abaixo:
• Windows Vista Enterprise Edition SP1.
• Visual Studio Team System 2008 (2008 9.0.21022.8 RTM).
• .NET Framework 3.5.
• Compilador C# 3.5.21022.8

2 Demonstração

Veja abaixo um exemplo de utilização do atributo Obsolete:

public class User
{
    private System.Collections.Generic.Dictionary<int, string> users;

    [System.Obsolete(”Esta propriedade está obsoleta.”, true)]
    public System.Collections.Generic.Dictionary<int, string> Users
    {
        get
        {
            return this.users;
        }
    }

    public User()
    {
        this.users=new System.Collections.Generic.Dictionary<int,string>();
        this.users.Add(0, “Evandro de Paula”);
    }
}

Note que a propriedade Users foi marcada como obsoleta, onde os parâmetros abaixo foram definidos como:
message = “Esta propriedade está obsoleta” (mensagem de erro ou alerta que é exibida durante a compilaçào quando a propriedade for utilizada).
error = true (indica que a utilização da propriedade obsoleta deve implicar em um erro de compilação).

Conforme o esperado, quando compilamos o código abaixo, obtemos um erro na linha em destaque:

class Program
{
    static void Main(string[] args)
    {
        User user = new User();
        System.Collections.Generic.Dictionary users=user.Users;
        System.Console.ReadLine();
    }
}

Entretanto, se implemetarmos a alteração em destaque abaixo, onde não utilizamos diretamente a propriedade obsoleta, mas sim um elemento da coleção, notaremos que nenhum erro é informado durante o processo de compilação:

class Program
{
    static void Main(string[] args)
    {
        User user = new User();
        System.Console.WriteLine("Name: " + user.Users[0]);
        System.Console.ReadLine();
    }
}

3 Conclusão

Mantenha atenção redrobrada no emprego do atributo Obsolete na tentativa de minimizar a possibilidade de comportamentos inesperados pelo sistema.
A boa notícia é que a correção deste bug já foi providenciada pelo time da Microsoft e deve estar disponível na próxima versão da plataforma .NET.

4 Código-fonte

Você pode baixar o código-fonte desta ferramenta no endereço http://www.orchestratechnology.com.br/blog/csharp/ObsoleteCheck.zip.

1 Objetivo

Desenvolvi a ferramenta VS2008SolutionDowngrader com o propósito de converter soluções criadas no Visual Studio 2008 para o Visual Studio 2005. É importante mencionar que a ferramenta foi desenvolvida com o intuito de migrar apenas soluções com projetos C#.

Um backup dos arquivos .sln e .csproj. é realizado antes que o processo de conversão seja executado, isso garante que você não perca a versão original dos seus arquivos em caso de uma falha na ferramenta.

2 Demonstração

Abaixo você pode acompanhar uma demonstração de conversão da solução VS2008CSharpSolution, criada noVisual Studio Team System 2008, contendo 5 projetos do tipo: Class Library, Console Application, ASP.NET web site, Windows Application e Windows Service:

Solução criada no Visual Studio Team System 2008:

Solução criada no Visual Studio Team System 2008

Executando a ferramenta de conversão:

Executando a ferramenta

Resultado da execução:

Output 1
Output 2

Abrindo a solução no Visual Studio Team System 2005:

Output 2

3 Instalador

O instalador está disponível no endereço http://www.orchestratechnology.com.br/blog/ferramentas/VS2008SolutionDowngraderSetup.zip .

4 Código-fonte

Você pode baixar o código-fonte desta ferramenta no endereço http://www.orchestratechnology.com.br/blog/ferramentas/VS2008SolutionDowngrader.zip .

1 Introdução

No SQL Server é possível criarmos dois tipos de arquivos de dados, o primário e o secundário, sendo o primeiro tipo mandatório. De acordo com a documentação é possível criarmos 32.766 arquivos secundários.

Uma boa prática é deixar o arquivo de dados primário para o catálogo do banco de dados e armazenar os dados e objetos, tais como, tabelas, procedimentos armazenados, visões, funções, etc., em arquivos secundários. Desta forma, podemos reduzir a contenção no acesso aos dados.

Grupos de arquivo são estruturas lógicas de agrupamento de arquivos que podem ser gerenciados como uma unidade. Assumindo a recomendação apresentada no parágrafo anterior como premissa, por conseqüência é uma boa prática definir o arquivo de grupo do arquivo secundário como padrão, pois nele serão armazenados os dados e os objetos do banco de dados.

Veja o exemplo abaixo:

--CRIA O BANCO DE DADOS
PRINT 'Criando o banco de dados OrchestraTechnologyBlog...'
CREATE DATABASE OrchestraTechnologyBlog
ON
	PRIMARY
	(
		NAME='OrchestraTechnologyBlog',
		FILENAME='C:Program FilesMicrosoft SQL ServerMSSQL.1MSSQLDataOrchestraTechnologyBlogCatalog.mdf',
		SIZE=100MB,
		MAXSIZE=300MB,
		FILEGROWTH=50MB
	),
	FILEGROUP OrchestraTechnologyBlogFG1
	(
		NAME='OrchestraTechnologyBlogData1',
		FILENAME='C:Program FilesMicrosoft SQL ServerMSSQL.1MSSQLDataOrchestraTechnologyBlogData1.ndf',
		SIZE=500MB,
		MAXSIZE=UNLIMITED,
		FILEGROWTH=500MB
	)
	LOG ON
	(
		NAME='OrchestraTechnologyBlogLog',
		FILENAME='C:Program FilesMicrosoft SQL ServerMSSQL.1MSSQLDataOrchestraTechnologyBlogLog.ldf',
		SIZE=250MB,
		MAXSIZE=1GB,
		FILEGROWTH=15%
	)
GO
PRINT '>> Procesimento finalizado'

--DEFINE O FILEGROUP DE DADOS E OBJETOS DE BANCO COMO DEFAULT
PRINT 'Definindo o FILEGROUP OrchestraTechnologyBlogFG1 como padrao...'
ALTER DATABASE
	OrchestraTechnologyBlog
MODIFY FILEGROUP
	OrchestraTechnologyBlogFG1 DEFAULT
GO
PRINT '>> Procedimento finalizado'

2 Pontos de atenção

• Caso a propriedade o SIZE não seja especificada com um valor para arquivos do tipo secundários ou para o arquivo de log, os mesmos serão criados com o tamanho de 1MB.

• O valor máximo que pode ser definido na propriedade MAXSIZE para arquivos do tipo primário é de 16TB e para arquivos de log de 2TB. É possível definir esta propriedade como UNLIMITED para que o tamanho do arquivo cresça até que o espaço em disco acabe.

• O número 0 no FILEGROWTH serve para indicar que o arquivo não cresça automaticamente quando for necessário.

3 Boas práticas

• A recomendação da Microsoft para as extensões dos arquivos primário, secundário e de log é: .mdf para o arquivo primário, .ndf para arquivos secundários e .ldf para arquivo de log.

• Baseado no plano de crescimento do banco de dados crie os arquivos com o maior tamanho possível para evitar a fragmentação, que por sua vez, exerce pressão no processo de I/O.

• Caso opte por utilizar o UNLIMITED no MAXSIZE, é vital ter um mecanismo para monitorar o espaço em disco que envie alertas quando o mesmo estiver acabando, como por exemplo, o SCOM 2007.

O exemplo abaixo é um código que compila sem problema algum, porém, durante a sua execução lança a exceção System.ArrayTypeMismatchException na linha em que o inteiro 1 é atribuído a posição 0 do array b.

using System;

namespace CompilerTypeCheck
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string[] a = new string[3];
                object[] b = a;
                b[0] = 1;
            }
            catch (System.ArrayTypeMismatchException atmex)
            {
                System.Console.WriteLine("An error occured while executing this program. Error details: " + atmex.StackTrace);
            }

            System.Console.WriteLine("Press  to exit…”);
            System.Console.ReadLine();
        }
    }
}

1 Objetivo

O propósito deste artigo é apresentar os procedimentos para gerar uma documentação de código a partir dos comentários XML.

2 Requerimentos de sistema

A solução proposta foi desenvolvida utilizando-se os softwares abaixo:
• Windows Server 2003 R2 Enterprise Edition SP2.
• .NET Framework 2.0.
• Visual Studio 2005 Team Suite.
• HTML Help WorkShop
• SandCastle 2.3.8000.26.
• SandCastle Help File Builder 1.6.0.2.

3 Acrônimos

Acrônimo Descrição
VO Value Object
CHM Compiled HTML Help

4 Procedimentos

4.1 Configuração do Visual Studio.NET

A primeira etapa do procedimento é configurar os seus projetos no VS.NET para gerarem o arquivo XML de documentação quando mesmo for compilado. Para obter este resultado, siga para as propriedades do projeto e selecione a opção XML documentation file na seção Build, como mostra a ilustração abaixo:

http://www.orchestratechnology.com.br/blog/vsnet2005/ConfiguringXMLGeneration.JPG

4.2 Comentando o seu código

A utilização de comentários no código é muito importante, talvez não para você mesmo naquele momento da confecção do código, mas quando tiver de realizar alguma manutenção corretiva ou preventiva depois de alguns meses ou quando outra pessoa suportará seu código. Portanto, não confie na sua boa memória, comente seu código. Abaixo segue um exemplo de uma classe (VO) comentada:

using System;

namespace OrchestraTechnology.SandCastle.VO.Security
{
    /// <summary>
    /// Classe para transferência dos dados de um usuário.
    /// </summary>
    [System.Serializable]
    public class User
    {
        #region Attributes
        private string firstName;
        private string lastName;
        private string email;
        #endregion

        #region Properties
        /// <summary>
        /// Nome do usuário
        /// </summary>
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }

        /// <summary>
        /// Sobrenome do usuário
        /// </summary>
        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }

        /// <summary>
        /// Endereço de e-mail do usuário
        /// </summary>
        public string Email
        {
            get { return email; }
            set { email = value; }
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Construtor padrão.
        /// </summary>
        /// <example>
        /// <code>
        /// OrchestraTechnology.SandCastle.VO.Security.User user = new OrchestraTechnology.SandCastle.VO.Security.User();
        /// </code>
        /// </example>
        public User()
        {
        }

        /// <summary>
        /// Construtor alternativo.
        /// </summary>
        /// <param name="firtName">Nome do usuário</param>
        /// <param name="lastName">Sobrenome do usuário</param>
        /// <param name="email">Endereço de e-mail do usuário</param>
        /// <example>
        /// <code>
        /// OrchestraTechnology.SandCastle.VO.Security.User user = new OrchestraTechnology.SandCastle.VO.Security.User("Evandro", "Paula", "evandro@orchestratechnology.com.br");
        /// </code>
        /// </example>
        public User(string firtName, string lastName, string email)
        {
            this.FirstName = firstName;
            this.LastName = lastName;
            this.Email = email;
        }
        #endregion
    }
}

4.3 Inspecionando o arquivo XML gerado

Quando compilar o projeto uma arquivo XML será gerado de acordo com as configurações (diretório e nome do arquivo) realizadas no passo 5.2.

<xml version="1.0"?>
<xml version="1.0"?>
<doc>
    <assembly>
        <name>OrchestraTechnology.SandCastle.VO</name>
    </assembly>
    <members>
        <member name="T:OrchestraTechnology.SandCastle.VO.Security.User">
            <summary>
            Classe para transferência dos dados de um usuário.
            </summary>
        </member>
        <member name="M:OrchestraTechnology.SandCastle.VO.Security.User.#ctor">
            <summary>
            Construtor padrão.
            </summary>
            <example>
            <code>
            OrchestraTechnology.SandCastle.VO.Security.User user = new OrchestraTechnology.SandCastle.VO.Security.User();
            </code>
            </example>
        </member>
        <member name="M:OrchestraTechnology.SandCastle.VO.Security.User.#ctor(System.String,System.String,System.String)">
            <summary>
            Construtor alternativo.
            </summary>
            <param name="firtName">Nome do usuário</param>
            <param name="lastName">Sobrenome do usuário</param>
            <param name="email">Endereço de e-mail do usuário</param>
            <example>
            <code>
            OrchestraTechnology.SandCastle.VO.Security.User user = new OrchestraTechnology.SandCastle.VO.Security.User("Evandro", "Paula", "evandro@orchestratechnology.com.br");
            </code>
            </example>
        </member>
        <member name="P:OrchestraTechnology.SandCastle.VO.Security.User.FirstName">
            <summary>
            Nome do usuário
            </summary>
        </member>
        <member name="P:OrchestraTechnology.SandCastle.VO.Security.User.LastName">
            <summary>
            Sobrenome do usuário
            </summary>
        </member>
        <member name="P:OrchestraTechnology.SandCastle.VO.Security.User.Email">
            <summary>
            Endereço de e-mail do usuário
            </summary>
        </member>
    </members>
</doc>

Note que nós são criados para manter as referências do assembly e seus membros, bem como como os comentários que foram inseridos.

4.4 SandCastle Help File Builder

A etapa final compreende na criação de um projeto no SandCastle Help File Builder referenciando os arquivos XML que são gerados durante a compilação e realizar o Build do projeto.

http://www.orchestratechnology.com.br/blog/vsnet2005/ConfiguringSandCastleBuilder.JPG

Um arquivo de ajuda com a extensão CHM, veja a ilustração abaixo:

http://www.orchestratechnology.com.br/blog/vsnet2005/CHMFile.JPG

5 Softwares

Os softwares utilizados neste artigo podem ser obtidos nos endereços abaixo:

HTML Help WorkShop
http://www.microsoft.com/downloads/details.aspx?FamilyID=00535334-c8a6-452f-9aa0-d597d16580cc&displaylang=en

SandCastle 2.3.8000.26
http://www.microsoft.com/Downloads/details.aspx?FamilyID=e82ea71d-da89-42ee-a715-696e3a4873b2&displaylang=en

SandCastle Help File Builder 1.6.0.2
http://www.codeplex.com/SHFB/Release/ProjectReleases.aspx?ReleaseId=8261

6 Código-fonte

É possível baixar o código-fonte utilizado para a elaboração deste artigo no endereço http://www.orchestratechnology.com.br/blog/vsnet2005/SandCastle_20080117_1712.zip.

Ward Cunningham.
http://www.aboutus.org/Ward_Cunningham

1 Objetivo

O propósito deste artigo é apresentar uma proposta de solução para que aplicações web suportem outras línguas, tais como: espanhol, inglês, etc. Também é objetivo deste documento guiar o processo de implementação da globalização, inclusive o processo de tradução.

2 Requerimentos de sistema

A solução proposta foi desenvolvida utilizando-se os softwares abaixo:
• .NET Framework 2.0.
• Visual Studio 2005 Team Suite.
• Microsoft Excel 2007.

3 Arquitetura da solução

3.1 Visão geral

A implementação da globalização será realizada utilizando-se arquivos de recursos locais (.resx) para cada uma das páginas. Desta forma, o trabalho em equipe pode ser facilitado, assim como o isolamento de possíveis bugs.
Na figura abaixo podemos identificar a utilização de arquivos de recursos locais para as páginas Default.aspx e Language.aspx nos idiomas português e inglês.
Os arquivos devem se nomeados utilizando o formato .aspx..resx. Note que os arquivos Default.aspx.resx e Language.aspx.resx não seguem este formato. Tais arquivos devem possuir o texto do idioma padrão da aplicação, pois toda vez que não for possível encontrar um arquivo de recurso local para o idioma preferido do usuário, estes serão utilizados.

ResxFiles - ResxFiles

O idioma a ser utilizado será obtido a partir das configurações do navegador.

BrowserLanguagePreferences - BrowserLanguagePreferences

Para obter tal resultado, devemos incluir a configuração destacada abaixo no web.config da aplicação:

<xml version="1.0"?>
<configuration>
	<appSettings/>
	<connectionStrings/>
	<system.web>
		<compilation debug="true"/>
		<authentication mode="Windows"/>
		<globalization culture="auto" uiCulture="auto"/>
	</system.web>
<configuration>

Em alternativa a uma configuração incorreta do browser ou a ausência de direitos para realizar tal configuração, as páginas deverão permitir que o usuário escolha o idioma preferido para visualizar as páginas. Tal escolha deverá ser gravada em um cookie, lida nas próximas visitas as páginas e deverá ter prioridade sobre as configurações do navegador.

O cookie pode ser gravado utilizando-se o código exemplo abaixo:

System.Web.HttpCookie cookie =
	new System.Web.HttpCookie("LanguagePreference", culture);
cookie.Domain="orchestratechnology.com.br";
cookie.Expires=System.DateTime.Now.AddDays(30);
this.Response.Cookies.Add(cookie);

A leitura do cookie e alteração do idioma corrente deverá ser realizada no evento Application_BeginRequest no arquivo Global.asax. Veja o exemplo abaixo:

void Application_BeginRequest(object sender, EventArgs e)
{
    System.Web.HttpCookie cookie =
	this.Request.Cookies["LanguagePreference"];
    if (cookie != null)
    {
        System.Threading.Thread.CurrentThread.CurrentUICulture =
	new System.Globalization.CultureInfo(cookie.Value, true);
    }
}

4 Procedimentos

4.1 Configuração para o idioma português

O primeiro passo para a implementação da globalização é criar a pasta App_LocalResources no projeto da aplicação web. Siga os passos:

• Clique com o botão direito do mouse no projeto web e escolha a opção “New Folder”. Em seguida, renomeie-a para App_LocalResources.

ProjectViewCreatingNewFolder - ProjectViewCreatingNewFolder

• Clique com o botão direito na pasta App_LocalResources e escolha a opção “Add New Item…”.

AppLocalResourcesFolderAddNewItem - AppLocalResourcesFolderAddNewItem

• Selecione o template “Resource File” e defina um nome para o arquivo de acordo com o formato .aspx.resx.

AddingDefault.aspx.resx - AddingDefault.aspx.resx

• Preencha o arquivo com os textos que deverão ser traduzidos. A coluna Name deverá ser preenchida de acordo com o formato .. Veja o exemplo abaixo:

FillingUpDefault.aspx.resx - FillingUpDefault.aspx.resx

• Edite a página com os atributos meta:resourcekey.


<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" meta:resourcekey="Page" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:LinkButton ID="lkbChangeLanguage" runat="server" OnClick="lkbChangeLanguage_Click" meta:resourcekey="lkbChangeLanguage"></asp:LinkButton>
        <br /><br />
        <asp:Label id="lblName" runat="server" meta:resourcekey="lblName"></asp:Label>
        <asp:TextBox id="txtName" meta:resourcekey="txtName" runat="server"></asp:TextBox>
        <br />
        <asp:Label id="lblSpecialty" runat="server" meta:resourcekey="lblSpecialty"></asp:Label>
        <asp:DropDownList id="ddlSpecialty" runat="server" meta:resourcekey="ddlSpecialty">
            <asp:ListItem meta:resourcekey="ListItem1"/>
            <asp:ListItem meta:resourcekey="ListItem2"/>
            <asp:ListItem meta:resourcekey="ListItem3"/>
            <asp:ListItem meta:resourcekey="ListItem4"/>
        </asp:DropDownList>
        <br />
        <asp:Label id="lblEmail" runat="server" meta:resourcekey="lblEmail"></asp:Label>
        <asp:TextBox id="txtEmail" runat="server" meta:resourcekey="txtEmail"></asp:TextBox>
        <br /><br />
        <asp:Button ID="btnInsert" runat="server" meta:resourcekey="btnInsert" />
    </div>
    </form>
</body>
</html>


4.2 Processo de tradução

Os passos descritos nesta seção foram desenhados para facilitar a interação entre o tradutor e o desenvolvedor.
Os exemplos contemplam apenas a tradução para o idioma inglês, pois para os demais o processo é o mesmo.

• Copie o arquivo Default.aspx.resx e cole na pastas App_LocalResources. Em seguida, altere o nome do novo arquivo para Default.aspx.en-us.resx.
• Selecione todos os textos do arquivo e cole em uma planilha Excel.

ResourceDataInExcel2007 - ResourceDataInExcel2007

• Trave todas as células da coluna A e destrave as da coluna B para que o tradutor não altere o ID.Property dos controles acidentalmente. Para isso, clique selecione as células da coluna, clique com o botão direito sobre a seleção e escolha Format Cells….

FormattingCells - FormattingCells

• Trave ou destrave as células selecionando o checkbox Locked.

LockingCells - LockingCells

• Proteja a planilha, clicando na aba Review e no botão Protect Sheet. Depois, informe uma senha e selecione os checkboxes de acordo com a figura abaixo:

ProtectingSheet - ProtectingSheet

• Envie a planilha para o tradutor.
• Quando a tradução estiver completa, exclua as linhas do arquivo de Default.aspx.en-us.resx e cole as linhas da planilha Excel.
• Repita os passos descritos acima para os demais idiomas.

5 Dica

Para facilitar a geração do arquivo de resource (.resx) para as páginas que já existem, é possível, a partir do modo design de visualização da página, utilizar a opção Generate Local Resource no menu Tools. Contudo, após a geração do arquivo será necessários normalizar os nomes dos controles.

Tip - Tip

6 Código-fonte

É possível baixar o código-fonte utilizado para a elaboração deste artigo no endereço http://www.orchestratechnology.com.br/blog/aspnet20/Globalization_20071109.zip.