Procurando por MCTs

by Israel Aece 30. April 2009 08:56

Como você já deve ter visto aqui, eu ministro treinamentos Microsoft na área de desenvolvimento, em um centro oficial em Campinas – SP, chamado People Computação.

Como está havendo uma grande demanda para cursos de .NET 2.0 e 3.5, ela está recrutando MCTs que possuem alguma certificação MCPD (exigência da Microsoft) e que esteja disposto e tenha disponibilidade para ministrar tais treinamentos. Se você estiver interessado, entre em contato comigo para que eu possa indicá-lo e colocá-lo em contato com a pessoa responsável. Questões de cronograma, valores, etc., deverão ser tratados diretamente com a People.

Tags:

General

Table-Valued Parameter

by Israel Aece 29. April 2009 23:57

Suponha que você tenha uma lista na sua aplicação, onde cada um dos elementos desta lista representa  um Id na base de dados. Você precisa submeter esta lista para uma Stored Procedure para atualizar os respectivos registros. Aqui entra o problema: como você irá fazer isso?

Provavelmente você já deve ter passado por esse problema, e as possíveis soluções para isso seria percorrer a lista, elemento à elemento, configurar o(s) parâmetro(s) e, finalmente, invocar a Stored Procedure. Outra possibilidade seria formatar todos os Ids em uma única String, separados por uma vírgula, e na Stored Procedure criar um parâmetro do tipo Varchar(X) para receber tais Ids. O problema da primeira técnica é a quantidade de comandos que você executa, ou seja, se tiver 200 Ids, serão duzentas execuções da Stored Procedure; já a segunda nos obrigará a criar uma query dinâmica, o que poderá tornar o nosso código vulnerável à SQL Injection e, além disso, se a concatenação dos Ids na String resultar em uma String maior do que o comprimento do parâmetro, a query não executará como o esperado.

Uma forma elegante de resolver isso no SQL Server 2008, é utilizando um novo tipo de dado, chamado de Table-Valued Parameter. Com este tipo especial, é possível determinarmos uma estrutura de dados e, definí-lo como parâmetro de entrada em uma Stored Procedure. O código abaixo ilustra a criação do Table-Valued Parameter e, logo em seguida, a Stored Procedure que utiliza o mesmo:

CREATE TYPE ColecaoDeIds AS TABLE
(
    Id INT NOT NULL
)
GO

CREATE PROCEDURE AtualizarUsuarios
    @ColecaoDeIds As ColecaoDeIds READONLY,
    @Ativo As Bit
AS
BEGIN
    UPDATE
Usuarios SET
        Ativo = @Ativo
    WHERE Id IN
    (
        SELECT Id FROM @ColecaoDeIds
    )
END
GO

Note que o tipo “ColecaoDeIds” contém apenas uma coluna chamada “Id”, mas você poderia adicionar quantas forem necessárias. Um detalhe importante é que, quando utilizamos um Table-Valued Parameter como parâmetro em uma Stored Procedure, ele deverá obrigatoriamente ser definido como ReadOnly; se precisar inserir, atualizar ou excluir registros dele, então você deve inserir os dados em uma tabela temporária e, depois disso, fazer a manipulação desejada. O interessante é que o Table-Valued Parameter nada mais é que uma espécie de “tabela”, permitindo efetuar queries em cima dela.

Já no código .NET, poucas mudanças são necessárias. Basicamente o que você precisa fazer é, criar uma instância da classe SqlParameter e definir a propriedade SqlDbType para SqlDbType.Structured. Há uma limitação na definição do tipo de objeto que você pode passar como valor para este parâmetro: deverá utilizar DataTable, DbDataReader ou IEnumerable<SqlDataRecord>. Independentemente de qual destes repositórios você irá utilizar, obrigatoriamente eles devem seguir a mesma estrutura do Table-Valued Parameter que, no nosso caso, possui apenas uma coluna chamada “Id” do tipo INT. O código abaixo mostra como podemos proceder para a configuração deste parâmetro:

using (SqlCommand cmd = new SqlCommand(“AtualizarUsuarios”, conn))
{
    cmd.Parameters.Add(
        new SqlParameter(“@ColecaoDeIds”, tuaDataTableAqui) { SqlDbType = SqlDbType.Structured });
}

Se você já utiliza DataTables para armazenamento e/ou manipulação dos dados, então tudo o que precisa fazer é criar uma nova DataTable com a mesma estrutura do Table-Valued Parameter e populá-la. Mas e se estivermos utilizando algum array ou coleção? Para facilitar,, eu criei um extension method chamado ToDataTable<T> que, como o próprio nome diz, transforma a coleção/array em uma DataTable. Como a estrutura da DataTable precisa seguir a mesma estrutura do parâmetro, eu criei um atributo chamado GenerateColumnAttribute, para que você decore as propriedades de sua entidade, para que elas sejam criadas como DataColumns no DataTable. Com essa estrutura, poderíamos fazer algo como:

List<Usuario> list = CarregarUsuarios();

using (SqlCommand cmd = new SqlCommand(“AtualizarUsuarios”, conn))
{
    cmd.Parameters.Add(
        new SqlParameter(
            “@ColecaoDeIds”,
            list.ToDataTable(typeof(GenerateColumnAttribute))) { SqlDbType = SqlDbType.Structured });

    Console.WriteLine(cmd.ExecuteNonQuery());
}

O método ExecuteNonQuery retornará a quantidade de registros afetados pela query. O código .NET de exemplo pode ser encontrado aqui.

Tags: , ,

Data

Tuples

by Israel Aece 27. April 2009 23:55

Especulando o .NET Framework 4.0 no Reflector, eu vi que há uma estrutura de Tuples. Tuples é uma forma que temos para representar algum dado, ou um conjunto deles, sem necessariamente ter uma classe/estrutura por trás disso. Tudo na programação orientada à objetos e nas linguagens fortemente tipada, temos que criar fisicamente a classe e sua estrutura de propriedades para, em seguida, poder utilizá-la.

As Tuples tem um papel importante na programação dinâmica, e como sabemos que C# está cada vez mais ganhando alguns conceitos deste tipo, as Tuples trazem uma importante característica para o nosso código. Muitas vezes já nos deparamos com um cenário onde precisamos retornar mais do que um resultado. Neste caso, utilizamos o retorno tradicional do método em conjunto com alguns parâmetros de saída (out/ref). Apesar de conseguir contornar com a criação de tipos (classes) adicionais, as Tuples vão muito além, já que não há a necessidade da criação deste tipo.

Os tipos anônimos tem uma funcionalidade semelhante, mas tem um escopo limitado, podendo ser acessado somente dentro do bloco onde foi criado. As Tuples vão mais além, sendo possível definí-las como retorno de métodos, propagando para outros lugares.

As Tuples são imutáveis, com tamanho fixo e permite o acesso diretamente a cada um dos valores através de propriedades “dinamicamente criadas”. Assim como os tipos anônimos e variáveis declaradas com o “tipo” var, a tipificação será determinada através da atribuição do(s) valor(es) à Tuple. Notem que nos exemplos abaixo, não especificamos em nenhum momento os tipos que estamos trabalhando:

var tuple = Tuple.Create(1, “Israel Aece”); 
var id = tuple.Item1; 
var nome = tuple.Item2;

//ou algo assim:

var tuple = AlgumaFuncaoQueRetornaMaisDeUmValor();
var id = tuple.Item1; 
var nome = tuple.Item2;

Infelizmente, na versão atual do CTP do .NET 4.0, as classes que representam as Tuples estão definidas como internal. Essas classes estão sendo criadas para melhorar a interoperabilidade com o F#, mas espero que elas se tornem públicas até a versão final, para que possamos fazer uso em nossas aplicações.

Tags: ,

.NET Framework

Embutindo o PIA

by Israel Aece 24. April 2009 22:57

Quando referenciamos um componente COM em um aplicativo .NET, o Visual Studio .NET nos auxilia na criação de um Assembly de Interoperabilidade, conhecido como Primary Interop Assembly, ou somente PIA. Na verdade, a IDE recorre à um utilitário chamado tlbimp.exe, que dado um determinado componente COM, gera uma DLL com toda estrutura (tipos) do componente COM, já “traduzindo” os tipos COM para tipos .NET, facilitando assim o consumo por uma aplicação .NET.

Uma das melhorias que o .NET 4.0 está trazendo é a possibilidade de embutirmos esse Assembly de interoperabilidade no Assembly da aplicação. Para isso, basta ir até as propriedades da referência COM e definir a propriedade Embed Interop Types como True. Isso evita ter um Assembly exclusivo para servir como “ponte” entre a aplicação .NET e o componente COM. Lembro-me de alguns poucos projetos que tivemos que utilizar esse recurso que, como se já não bastasse o overhead que é causado pelo RCW, a distribuição era terrível, já que tínhamos que registrar efetivamente o componente COM no Windows, e instalar o Assembly de interoperabilidade e a aplicação em si.

Além de facilitar a distribuição, esse recurso ainda se preocupa em inserir no Assembly da aplicação somente os tipos necessários que a mesma utiliza, diminuindo consideravelmente o tamanho final da mesma. Podemos notar isso através da imagem abaixo:


PIA

Tags: ,

.NET Framework | Interoperabilidade

Model-First Development

by Israel Aece 23. April 2009 11:13

A versão atual do Entity Framework trabalha com o conceito conhecido como “database-first”. Neste caso, você precisa primeiramente criar a base de dados, definir as tabelas, as colunas e suas características, constraints e, depois disso, a IDE analisará todo o schema da mesma e irá construir o modelo de classes olhando para ele, inclusive levando em consideração os possíveis relcionamentos definidos, para tentar criar as associações entre as classes que farão parte do sistema. Quando você tiver tem uma base de dados que está bem definida e funcional, esse modelo é bem interessante, já que ele (re)utiliza todo o trabalho que foi realizado na construção da mesma, tendo apenas que acertar alguns detalhes.

Mas o mapeamento entre o mundo relacional e orientado a objetos é bem mais complexo do que isso. Nem sempre temos uma entidade por registro/tabela. Algumas características que são salvas no banco de dados como uma coluna normal, utilizando um tipo de dado convencional, no mundo orientado à objetos, isso pode ser representado por uma especialização (herança) ou até mesmo um outro objeto mais complexo que possui, além de suas características (propriedades), um funcionamento próprio (métodos e eventos). Esses são alguns dos “problemas” encontrados neste modelo de desenvolvimento que o Entity Framework atualmente possui.

Eu coloquei a palavra problemas entre aspas que, ao meu ver, isso é uma característica deste modelo e não uma deficiência. Aqueles que muitas vezes optam por iniciar no desenvolvimento da estrutura de classes da aplicação, não irá ter benefício nenhum do uso desta técnica. A partir da versão 2.0 do Entity Framework, que será lançada em conjunto com o .NET Framework 4.0 e o Visual Studio .NET 2010, irá incorporar o modelo de desenvolvimento conhecido como “model-first” que, como o próprio nome diz, baseando na estrutura de classes e suas associações, conseguirá extrair o modelo relacional, gerando os scripts necessários para a criação das tabelas, colunas e possíveis relacionamentos em uma base de dados.

Tags:

Data

Otimizando a compilação

by Israel Aece 16. April 2009 09:34

Quando fazemos alguma mudança no diretório bin, App_Code ou no arquivo Global.asax, toda a aplicação ASP.NET será recompilada. Para sites pequenos, isso não tem muitos problemas, já que não há muitos arquivos/recursos a serem compilados. Já quando temos um site com várias páginas, esse processo pode se tornar muito lento, principalmente na primeira requisição, que é o onde a compilação irá ocorrer.

O SP1 do .NET Framework 3.5 inclui um novo atributo chamado optimizeCompilations, dentro do elemento compilation. Quando esse atributo estiver definido como False (configuração padrão), qualquer mudança provocará a recompilação total do site; já quando voce, explicitamente, definí-lo como True, somente os arquivos afetados pela mudança serão recompilados. Abaixo temos o exemplo da utilização deste novo atributo:

<compilation optimizeCompilations="true">

Tags: ,

ASP.NET

WSDL com nome da máquina

by Israel Aece 14. April 2009 22:32

Quando publicamos um serviço WCF em um servidor, mais precisamente, dentro do IIS, é comum aparecer o nome da máquina no endereço de acesso ao documento que descreve o serviço (WSDL). Como se isso não bastasse, dentro do WSDL ainda existem diversos outros links, que também utilizam o nome da máquina para compor o endereço. Mas o correto seria aparecer o nome do domínio ou, até mesmo, o IP do servidor onde o serviço está hospedado.

Isso ocorre porque o WCF utiliza as configurações do IIS (binding information) para determinar o base address do serviço. Para resolver isso, podemos atualizar as configurações do IIS. Caso esteja utilizando o IIS 6.0, então pode adicionar um host header customizado nas configurações do Web Site, ou ainda, através do seguinte comando:

C:\WINDOWS\system32\>cscript.exe %systemdrive%\inetpub\adminscripts\adsutil.vbs set w3svc/<ID do Web Site>/ServerBindings ":80:www.dominio.com.br"

Se estiver utilizando o IIS 7.0, pode recorrer a configuração do arquivo applicationHost.config, assim como é mostrado abaixo:

<bindings>
  <binding protocol="http" bindingInformation="*:80:www.dominio.com.br" />
</bindings>

E, finalmente, se já estiver utilizando o .NET Framework 3.5 SP 1, então pode utilizar o elemento baseAddressPrefixFilters, assim como é mostrado neste post.

Tags: , ,

WCF

Powered by BlogEngine.NET 1.5.0.0
Theme by Mads Kristensen

Sobre

Meu nome é Israel Aece e sou especialista em tecnologias de desenvolvimento Microsoft, atuando como desenvolvedor de aplicações para o mercado financeiro utilizando a plataforma .NET. [ Mais ]

Twitter

Host