Microsoft Most Valuable Professional

Este post, diferente dos demais, não apresenta nenhuma técnica de acesso a dados, nenhum design pattern ou nenhuma ferramenta de desenvolvimento nova… Na verdade este post foi escrito para informar a todos o quanto estou feliz e orgulhoso em fazer parte do seleto grupo de profissionais Microsoft MVP do Brasil!

MVPLogo

O prêmio Microsoft MVP (Most Valuable Professional) é uma iniciativa da Microsoft a fim de reconhecer o trabalho dos profissionais que compartilham sua experiência e seus conhecimentos com a comunidade técnica através de fóruns, blogs, sites, palestras, artigos e outros meios.Leia mais »

Windows Phone – Teste de Performance

Participando de um projeto de Windows Phone surgiu a necessidade de testar a performance do aparelho, e da plataforma em si. Este teste tinha como base a pergunta: "O quão rápido é o aparelho ao carregar uma quantidade X de elementos em um listbox?"

Essa dúvida surgiu devido a característica do aplicativo de armazenar registros diariamente, e na qual o usuário poderia listar uma quantidade bastante grande de registros na interface visual. Diante deste cenário muitas dúvidas surgiram: "Quanto tempo leva para carregar o controle?", "Qual a quantidade ideal de registros a serem carregados?", "Como o silverlight vai se comportar ao carregar uma quantidade grande de itens?", "O layout esta complexo o suficiente para fazer o aplicativo ficar lento?" "Quanto esses dados em memória podem deixar o device lento?"

Essas dúvidas poderiam apenas ser respondidas com um experimento, e este trabalhou coube a mim. Diante disso construí um teste de carga bastante simples, cujo funcionamento era: Criar muitos registros na base do SQL CE e listar uma quantidade bastante grande de registros de uma única vez.

Então, criei três funções básicas no aplicativo, sendo elas:

1 – Geração de valores: esta funcionalidade inseria 1000 registros no SQL CE toda vez que fosse acionada, populando a base com uma quantidade grande (comparada ao porte do dispositivo) de registros. A estrutura da classe que produziu esses dados na base de dados é a da imagem abaixo:

[Table(Name="tbLoadTest")]
public class TargetItem
{
    [Column(Name="ldtId", IsPrimaryKey=true, IsDbGenerated=true, CanBeNull=false,AutoSync=AutoSync.OnInsert)]
    public int Id { get; set; }

    [Column(Name="ldtTitle", CanBeNull=false)]
    public string Title { get; set; }

    [Column(Name = "ldtDescription", CanBeNull = false)]
    public string Description { get; set; }

    [Column(Name = "ldtValue", CanBeNull = false)]
    public decimal Value { get; set; }

    [Column(Name = "ldtInsertDate", CanBeNull = false)]
    public DateTime InsertDate { get; set; }
}

2 – Apagar itens do banco de dados: para limpar o banco de dados (e não deixar meu celular poluído) foi criada uma funcionalidade de expurgo dos dados.

3 – Listagem de arquivos: essa é a motivação de nosso teste de carga. Saber o quão rápido um determinado layout poderia ser carregado na tela do device e qual a quantidade ideal de registros que podem ser carregados sem interferir na performance do aparelho.

O interface do teste de carga ficou assim:

performance

RESULTADOS

Os resultados foram bastante interessantes. A carga de mil itens foi bastante rápida, em menos de 1,5 segundos foi possível incluir mil registros de uma única vez no SQL Ce. A carga de itens no listbox foi mais surpreendente ainda, em 1 segundo foram carregados mil itens na tela, em 2 segundos foram carregados mil registros e em 3,5 segundos foram carregados cinco mil registros na tela. O único ponto que a performance não agradou foi a parte de exclusão de registros, pois ela demorou muito para excluir todos os registros (demorou 1m35s para excluir 5000 registros), possivelmente isso esteja atrelado ao funcionamento do SQL CE e de seu transaction log.

Mas em suma, a performance do Windows Phone esta acima do esperado e seus resultados foram bastante satisfatórios.

APARELHO UTILIZADO

Samsung I8700 Omnia 7

OS: Microsoft Windows Phone 7.5

Chipset: Qualcomm QSD8250 Snapdragon

CPU: 1 GHz Scorpion

GPU: Adreno 200

Referência: http://www.gsmarena.com/samsung_i8700_omnia_7-3537.php

Erro na configuração do Team Foundation Server 2010

Ao tentar configurar o Team Foundation Server 2010 eu estava sendo barrado pela seguinte mensagem de erro:

TF255356: The following error occurred when configuring the Team Foundation databases: Error occurred while executing servicing step Create Warehouse for component TfsWarehouse during Install: Failed to add ASGARD\Administrator account to the TfsWarehouseDataReader role on the Tfs_Warehouse relational database.. For more information, see the configuration log.

figura01

Pesquisei na web e encontrei o seguinte comando (neste link http://support.microsoft.com/kb/2025896):

tfssecurity /g- "Sharepoint Web Application Services" "ASGARD\Administrator" /server:"http://win-mtagtaoa14r/" command

Após executar o comando, e na espera por solucionar o problema, vi que o comando não havia solucionado a questão…

Então olhei no arquivo de log e vi a mensagem "checking if login exists ASGARD\Administrator is not a login. creating login".

Percebi então que o usuário do banco de dados estava com o nome "WIN-MTAGTAOA14R\Administrator". Apaguei esse usuário e criei o usuário "ASGARD\Administrator" (ASGARD no caso é o meu domínio fictício e WIN-MTAGTAOA14R o nome de minha máquina virtual).

Após excluído o usuário antigo, e criado o novo usuário com o domínio correto rodei novamente o wizard de configuração do Team Foundation Server 2010 e terminei a instalação.

Moral da histório: antes de olhar na web, leia o arquivo de log.

figura02

Fica a dica!
[]s!

Construindo sua camada de acesso a dados com o Entity Framework 4.1

O Entity Framework 4.1(EF41) Code First veio para ajudar os desenvolvedores no processo de construção da camada de acesso a dados de suas aplicações. Ao contrário dos demais modelos do Entity Framework, o modelo Code First tem por objetivo criar o banco de dados seguindo como base a estrutura de nossas classes – os demais modelos, conhecidos como Table First, baseavam a criação das classes no modelo existente em nosso banco de dados. A vantagem da utilização do Code First é a possibilidade de criar um modelo de classes muito mais próximo a nossa necessidade, ao contrário das abordagens anteriores que produziam um modelo de classe “adaptado” de nossa estrutura de banco de dados.

Neste exemplo vamos discutir os modos de implementação de diferentes modelos de relacionamentos (e.g. um-para-muito, muitos-para-muitos, um-para-um) utilizando o ADO.Net Entity Framework 4.1. Além disso, quero mostrar algumas novas features e dar algumas dicas de como nos adequar ao Entity Framework 4.1.

Vamos começar! Alegre

Obs.: Para fazer download do código-fonte acesse este link: http://code.msdn.microsoft.com/Construindo-sua-camada-de-de659425.

1 – Nosso projeto de teste

Para este teste criaremos um cadastro de Clientes, Fabricantes, Produtos e Ordens de Compra. Neste modelo um cliente pode efetuar diversas ordens de compras, sendo que cada comprar pode conter um ou mais produtos, onde cada produto pode estar atrelado a uma ou mais ordens de compra. Além disso, um produto obrigatoriamente contém um fabricante. Nosso diagrama de classes será o seguinte:

diagrama

2 – Camadas da aplicação

Para este exemplo adotei os design patterns MVC e DAO. Os projetos estão dispostos como a imagem a seguir:

Projects

Commerce.Controler: corresponde a camada de controle de nossa aplicação.

Commerce.Entity: possui todas as entidades lógicas de nossa aplicação, além das interfaces que devem ser implementadas pelas demais camadas.

Commerce.Data: responsável pela funcionalidade de armazenamento das informações, esta camada engloba todo o uso do Entity Framework 4.1, diminuindo a dependência do projeto a um tecnologia. Isso permite a fácil manutenção e alteração da tecnologia, sem gerar impactos globais por toda a aplicação.

Commerce.Console: camada de apresentação e consumo dos recursos.

3 – Estratégia de criação da base de dados

Para definir a estratégia de criação do banco de dados fazemos uso de inicializadores.A estratégia default é a DropCreateDatabaseIfModelChanges, que apaga o banco de dados e o recria, além dessa estratégia ainda existem outras duas, sendo elas: DropCreateDatabaseAlways e CreateDatabaseIfNotExists. O time de produto do ADO.Net trabalha hoje em um projeto chamado Code First Migration, que trata do processo de adequação do modelo do banco de dados com as atualizações de suas entidades, sem que seja necessário apagar e recriar o banco de dados. Para fazer uso dos inicializadores de bancos de dados crie em seu DataContext um construtor que defina a estratégia de criação da base de dados como a seguir:

SetInitializer

4 – Remoção de convenções do Entity Framework 4.1

Para efetuar o mapeamento automático de nossas tabelas, o EF41 adota algumas convenções de nomenclatura, tipos de dados, e outros recursos. Para adicionar ou remover convenções devemos sobrescrever o método OnModelCreating de nosso DataContext. Em nosso exemplo removerei duas convenções: IncludeMetadataConvention, que evita a criação da tabela EdmMetada, que é uma tabela que contém um código uma única linha com um código hash utiliza para verificar se o modelo de nosso código é o mesmo do modelo de nosso banco de dados (mais informações aqui: http://blog.oneunicorn.com/2011/04/08/code-first-what-is-that-edmmetadata-table/); e PluralizingTableNameConvention, que é um atributo que evita que a nome das tabelas seja pluralizado, isto é, se você possui uma entidade chamada Carro, a tabela criada automaticamente no banco de dados se chamará Carro, e não Carros como a convenção do EF41 faz.

Conventions

5 – Tipos complexos

É bastante comum em nossas aplicações a necessidade de utilizarmos atributos que apenas servem como “agrupadores” de dados, e que na verdade não deve ser mapeamos em uma única tabela dedicada a eles. Podemos adotar como exemplo um tipo de dados Endereço. Uma classe chamada Endereço é bastante importante para agrupar informações de localidade, mas não possui características que exijam mapeamento para uma tabela dedicada exclusivamente para isso. Diante deste cenário devemos fazer uso do atributo ComplexType. Este atributo quando utilizado indica que nossa classe é um tipo complexo, que não deverá ser persistido em uma tabela própria, e que estará vinculado a atributo de alguma classe. Podemos indicar que uma classe é um tipo complexo de duas maneiras, sendo elas:

2.1 – No corpo da classe, indicando através do atributo ComplexType:

ComplexType01

2.2 – Indicando o tipo complexo em nosso DataContext, dentro do método OnModelCreating:

ComplexType02

Ultimamente tenho pensado que é mais interessante configurar o mapeamento de nossas classes dentro do DataContext do que em nossas classes através da utilização de atributos. Acredito que essa é a melhor forma, pois nosso projeto de entidades ficará livre de mais dependências, necessitando apenas de recursos nativos do Framework .

6 – Entidade base para persistência de dados em fontes de dados

É interessante, ao implementarmos nossas entidades, a criação de uma entidade base que defina atributos obrigatórios para todas as entidades. Neste exemplo criei uma entidade chamada DataEntity que contém três atributos: Id, atributo do tipo inteiro que servirá como chave primária de nossas entidades na base de dados; GlobalId, atributo do tipo GUID que fornecerá um identificador global a nossos registros dentro da base de dados; e Created, atributo do tipo DateTime que informará a data de criação de nossas entidades.

dataEntity

A utilização dessa classe como entidade base exige duas implementações em nossas entidades:

1 – Herança

Herança

2 – Invoque ao construtor da classe base em nossas entidades

construtor

7 – Interface como contrato para os repositórios

Para implementação dos repositórios criei uma interface com um conjunto de métodos obrigatórios que se espera de um repositório.

IRepository

Nessa interface temos as assinaturas:

void Save(T target): este método deve ser responsável pela inclusão e atualização dos dados na base de dados. Uma vez executado deve garantir que os dados serão inclusos ou atualizados conforme a entidade passada por parâmetro.

void Delete(T target): método de exclusão de registros da base de dados. Quando invocado, deve apagar o registro passado por parâmetro da base de dados.

T GetById(int id): método que deve retornar o registro na base de dados que contiver em sua chave primária o valor passado por parâmetro.

T GetByGlobalId(Guid id): gosto bastante de utilizar um campo UNIQUEIDENTIFIER em meus registros, pois atribuímos ao registro uma chave de identificação única que o torna único em todo o banco de dados, independente de sua localização – assim como propostos em bases de dados orientadas a objetos.

IEnumerable<T> GetAll(): deve retornar todos os registros existentes na base de dados para a entidade consultada.

IEnumerable<T> ExecuteQuery(Func<T, bool> expression): este método faz consultas na base de dados utilizando como filtro a expressão passada por parâmetro.

Esta interface define o que é esperado por cada classe repositório, mas se notarmos ela utiliza um tipo genérico como parâmetro para sua implementação. Para refinarmos o seu uso e tornarmos nosso repositório reutilizável e expansível, acredito que devemos criar para cada classe repositório uma interface que implemente o contrato definido por IRepository<T>, mas que defina qual entidade será persistida ali. Tomemos como exemplo a interface do repositório de clientes, conforme código:

IClientRepository

Seu classe repositório deve implementar ICLientRepository e ser igual a seguinte implementação:

ClientRepository

Observem que nossa classe de repositório implementa a interface IClientRepository utilizando a entidade Client como alvo de nossas ações de persistência no banco de dados, e não um tipo de dados genérico, como utilizado na interface IRepository<T>.

Este uso é indicado ao construirmos nossos testes unitários, pois ao implementarmos nossos repositórios fakes já teremos nossos repositórios bem estruturados e prontos para extensão.

Outra dica para a construção de nossos testes unitários é tornar os repositórios parametrizáveis através de nossas classes controllers. Devemos criar uma assinatura de construtor que permita a parametrização do repositório que utilizaremos em nossa implementação, assim como é importante fornecer um construtor que defina um repositório padrão, caso não seja passado nenhum parâmetro para o repositório, podemos fazer isso desta forma:

clientController

Bom, espero que algumas dicas aqui descritas ajudem a implementação de suas aplicações com o Entity Framework 4.1. Bom estudo e continuem programando… Alegre

[]s!

Por
Fernando Henrique Inocêncio Borba Ferreira

Entity Framework 4.1 – Armazenamento de arquivos

No Entity Framework 4.1 o armazenamento de dados binários no banco de dados é mais simples. Antes, no LINQ to SQL, era preciso criar uma instância da classe System.Data.Linq.Binary, valorizá-la com os dados binários e atribuí-la a sua propriedade correspondente em nossa entidade. Agora este cenário é mais simples, pois para persistir dados binários é apenas preciso criar uma propriedade do tipo byte[] (byte array) e lhe atribuir os dados diretamente.

Nesta demonstração iremos armazenar dados de qualquer arquivo selecionado, através de uma caixa de dialogo, no banco de dados. Iremos armazenar em nossa tabela: nome do arquivo, caminho, extensão, um valor para checksum e sua representação em binários.

Um checksum (ou hash sum) é uma sequência de dados de tamanho fixo, calculada a partir de um conjunto de dados binários. É um conceito bastante utilizado em tarefas de armazenamento e transmissão de dados. Seu funcionamento se dá pela seguinte forma: 1 – Calcula-se o checksum; 2 – Executa-se o armazenamento ou a transmissão dos dados; 3 – Calculsa-se o checksum dos dados recebidos; 4 – Verifica-se se o checksum calculado antes do armazenamento/envio é o mesmo da recepção, se sim, então os dados trafegaram com sucesso, se não, ocorreu algum desvio ou perda de dados durante o tráfego.

Para o cálculo do checksum utilizamos o algoritmo MD5, existem outros algoritmos de Hash que são mais seguros e produzem sequências maiores (i.e SHA1, SHA256, SHA512). Mas para este exemplo o MD5 é suficiente.

Abaixo o algoritmo utilizado para gravação dos dados binários no banco de dados, além do checksum:

Aqui estão os códigos da classe Arquivo (a entidade que será persistida no banco de dados), a classe ContextoDados (classe que herda de DbContext e faz o papel de proxy para nossas requisições com o banco de dados), e a classe Config (que é responsável por acessar configurações de nossa aplicação, como por exemplo a string de conexão).

Detalhe importante, para a coluna que irá conter os dados binários, o Entity Framework 4.1 criou na tabela uma coluna do tipo varbinary(max).

 

Para fazer download do exemplo acessem http://code.msdn.microsoft.com/Entity-Framework-41-6a79eb9e

[]s e até o próximo!

Por
Fernando Henrique Inocêncio Borba Ferreira.

Entity Framework 4.1 – Validations

O Entity Framework 4.1 fornece uma grande variedade de ferramentas para validação de dados. Neste exemplo vamos apresentar algumas das técnicas que podemos encontrar dentro do EF 4.1.

Data Annotations

Data Annotations são atributos, contidos no namespace System.ComponentModel.DataAnnotations, que quando adicionados em nossas classes fornecem características a nossos atributos e as suas respectivas colunas no banco de dados. Alguns desses atributos possuem caráter de validação, como: Required, exige que o campo seja preenchido; MaxLength, limita o tamanho do campo a uma quantidade máxima de caracteres; e MinLength, indica a quantidade mínima de caracteres.

efValidationPeople

Ao tentar salvar os dados na base de dados se algumas das restrições não estiverem sendo atendidas exceptions serão lançadas.

Fluent API Validations

O uso de Fluent API substitui o uso de Data Annotations e resulta no mesmo funcionamento. Ao contrário dos Data Annotations, as restrições não são inclusas na entidade, elas são inclusas no método OnModelCreating da classe de contexto com o banco de dados.

efValidationDataBaseContextFull

IValidatableObject

Para validações mais complexas que exijam alguma lógica ou verificação dentro de um contexto, a interface IValidatableObject, contida no namespace System.ComponentModel.DataAnnotations, fornece o método Validate que é invocado durante o comando SaveChanges, ou que pode ser chamado a qualquer momento que quisermos validar o conteúdo de nossa classe.

O método Validate retorna uma coleção de ValidationResults. Cada ValidationResult deve representar a validação efetuada, indicando a mensagem de erro e as propriedades que estão associadas com a validação.

efValidationPeopleFull

Executando validações prévias

Para execução de validações prévias, antes de executar o comando SaveChanges, é possível executar o método GetValidationErrors, presente no contexto com o banco de dados. Esse método retorna uma coleção de erros encontrados durante a validação das entidades adicionadas no contexto. O exemplo abaixo ilustra sua utilização.

efGetValidationErrors

Captura de exceções geradas por validações

Sempre que uma validação encontrar um erro dentro do domínio de entrada, uma exception do tipo DbEntityValidationException será disparada. Para receptar essas exceções e fazer o tratamento necessário, faça desta maneira:

efCapturaDeErros

Como pudemos ver, validações complexas devem ser tratadas pelo uso da interface IValidatableObject, enquanto que restrições de entrada (i.e. valores nulos, valores em branco, valores fora do tamanho esperado) deve utilizar Fluent API Validations ou Data Annotations. Entre o uso de Fluent API Validations ou Data Annotations, fico pelo uso de Data Annotations, pois utiliza uma sintaxe mais simples, mais fácil de ser escrita, mais fácil de ser entendida e segue um padrão sintático mais próximo ao das demais DataAnnotations.

Para fazer download do exemplo, acesse: http://code.msdn.microsoft.com/Entity-Framework-41-a701026d

Por
Fernando Henrique Inocêncio Borba Ferreira.

Entity Framework – Data Annotations

O Entity Framework (EF) permite que utilizemos nossas classes para construção e mapeamento de nosso banco de dados, para tanto algumas convenções são necessárias para que ocorra o mapeamento. Mas muitas vezes as convenções não são suficientes, pois em determinados cenários a representação de nossas classes não é a mesma representação de nosso banco de dados. Este post objetiva apresentar o uso de DataAnnotations (atributos de mapeamento) presentes no namespace  System.ComponentModel.DataAnnotations para construção de nossas classes. Abaixo seguem alguns dos atributos mais utilizados, seu modo de uso e seu impacto no banco de dados.

Key
As entidades mapeadas pelo Entity Framework precisam de uma propriedade que trabalhe como chave primária (propriedade chave), que trabalhe como “propriedade de rastreamento” do dado dentro da tabela, contendo um valor que diferencie o registro dos demais ali armazenados.  Por convenção, o EF procura em sua classe por uma propriedade nomeada como “Id” ou uma propriedade nomeada com o nome da classe concatenada a palavra “Id” (i.e. ProdutoId, PedidoId, ClienteId). Caso o EF não encontre uma propriedade que esteja dentro de suas convenções, então uma exception será disparada exigindo que a classe possua uma propriedade chave. Caso sua classe não possua uma propriedade cujo nome esteja dentro destas convenções então é possível utilizar o atributo Key para indicar qual propriedade de sua classe deverá funcionar como propriedade chave.

Impacto no banco de dados: será gerada uma primary key com identação automática (identity).

figuraAtributoKey

Required
O atributo Required indica que um atributo em particular é obrigatório e que não poderá deixar de ser valorizado.

Impacto no banco de dados: o uso deste atributo adiciona uma restrição “not null” na coluna gerada no banco de dados.

figuraDataAnnotationRequired

MaxLength e MinLength
Estes atributos validam o tamanho do dado inserido, limitando o tamanho máximo e/ou indicando seu tamanho mínimo.

Impacto no banco de dados: o tamanho das colunas criadas no banco de dados serão limitados pelo uso do atributo MaxLenght. O tamanho default das colunas, sem o uso do atributo MaxLenght, é de 128 caracteres.

figuraMaxLengthMinLength

NotMapped
Existem cenários onde nem todos os atributos de nossas classes devem ser mapeados para o banco de dados. Este cenário existe quando alguma das propriedades de nossa classe é resultante de alguma ação dinâmica ou cálculo, e que não precisa ser armazenada na base de dados.

Impacto no banco de dados: nenhum, esse atributo não acarreta na criação de nenhuma coluna, na verdade ele é ideal para que a coluna não seja criada.

figuraNotMapped

ComplexType
Não é incomum que nossa classes possuam propriedade que sejam instâncias de outros objetos, cujos dados não queremos armazenar em tabelas dedicadas. No nosso exemplo podemos incluir uma propriedade que indique qual o endereço de entrega de um malote, mas talvez não seja necessário possuir uma tabela exclusiva para o armazenamento dos endereços, podemos desejar que nossa tabela de malote possuísse as colunas de endereço dentre suas colunas. Para tanto, devemos utilizar o atributo ComplexType para indicar este cenário. Detalhe, este atributo deve ser incluído na classe que corresponde ao tipo complexo, não na classe que contém o atributo com o tipo complexo.

Impacto no banco de dados: nenhuma nova tabela será criada, em contraponto, as propriedades existentes na classe que  contém o atributo ComplexType serão mapeadas para a tabela que contém a propriedade que utiliza o tipo de dados.

figuraComplexType01

figuraComplexType02

Table and Column
Podem existir dois casos onde os nomes das colunas das tabelas não são os mesmos dos nomes dos atributos das classes,  sendo: o primeiro, quando o banco de dados já existe e é preciso criar o mapeamento para o mesmo; segundo, quando por alguma necessidade do cliente o banco de dados deve possuir uma nomenclatura de acordo com um conjunto de regras e padrões.

O atributo Table permite o mapeamento de uma classe para uma tabela, substituindo as conversões do Entity Framework.

figuraAtributoTable

O atributo Column permite a definição do nome da coluna que será mapeada pelo Entity Framework. No exemplo abaixo é  possível notar que também é possível a combinação de diferentes atributos de mapeamento em uma única propriedade.

figuraAtributoColumn

ForeignKey
O atributo ForeignKey indica qual propriedade na classe representa o campo que corresponde à chave estrangeira entre as tabelas. Note que no exemplo abaixo o atributo ForeignKey está acima da propriedade que representa a navegação entre as duas entidades.

figuraForeignKey

Por
Fernando Henrique Inocêncio Borba Ferreira.

Entity Framework 4.1 + MVC + DAO

Neste exemplo vamos demonstrar o uso dos design patterns MVC e DAO, combinados com a utilização do Entity Framework 4.1 como tecnologia de acesso a dados de nossa aplicação.

O MVC (Model-View-Controller) é um design pattern bastante utilizado no mercado devido a sua capacidade de dividir a aplicação em camadas especialistas em suas funções, favorecendo a alta coesão das mesmas. A camada model é responsável por representar o mundo real através do uso de objetos. A camada view é dedicada exclusivamente a apresentação dos dados, podendo ser uma aplicação web, uma aplicação console, um formulário do Windows, uma page Silverlight, ou qualquer outra tecnologia front-end. A camada controller faz ponte entre a camada view e a camada model, interceptando a comunicação entre as duas e aplicando regras, validações, redirecionamentos ou encapsulando a comunicação com diferentes frameworks e sistemas. Outra vantagem deste modelo é a possibilidade de criar módulos independentes que trabalhem de modo desacoplado, para que se tornem fáceis de serem substituídos e reutilizados.

O design pattern DAO (Data Access Object) tem o objetivo de encapsular todos os acessos as fontes de dados feitas na aplicação. O uso deste design pattern permite que nossa aplicação não fique dependente de uma tecnologia de acesso a dados, pois estaremos agrupando todas as regras e usos de frameworks específicos de acesso a dados em uma única camada que pode ser facilmente substituída. Caso seja necessária a substituição da tecnologia de armazenamento (exemplo: de MS SQL para Oracle, ou de MS SQL para SQL Azure, ou de Oracle para alguma tecnologia NoSQL) o impacto não será tão grande, e a adaptação do sistema será restrita, evitando impactos globais na aplicação.

Mãos a obra

Pare demonstrar o uso destes design patterns e do Entity Framework 4.1 criaremos um cadastro simples de carros e suas respectivas montadoras.

1 – Abra o Microsoft Visual Studio 2010 e crie uma solução em branco.
2 – Adicione um projeto class library, no nosso exemplo este projeto chamará SampleCore.
3 – Apague o arquivo “Class1.cs” que é criado automaticamente pelo Visual Studio. Faça referências ao namespace “System.Data.Entity” e ao Entity Framework 4.1, geralmente esta localizado no caminho C:\Program Files (x86)\Microsoft ADO.NET Entity Framework 4.1\Binaries\EntityFramework.dll, o download do EF 4.1 pode ser feito neste link: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8363
4 – Crie três pastas dentro do projeto, chamadas Model, Controller e Data.
5 – Crie as classes Carro e Montadora dentro de Model conforme os exemplos a seguir:

01

02

Observe que para representar o relacionamento um para muitos (entre a montadora e os carros) utilizamos o tipo de dados ObservableCollection. ObservableCollection representa uma coleção de dados dinâmica que fornece notificações quando os itens são adicionados, removidos ou quando toda a lista é atualizada.

6 – Agora vamos começar a trabalhar com nossa camada de acesso a dados. Antes de qualquer coisa, criaremos duas interfaces para nossos repositórios de montadoras e carros. As interfaces devem ser criadas dentro de Model e devem implementar a seguinte estrutura:

03

04

Crie dentro da pasta Data uma classe chamada ContextoBancoDados e faça-a herdar de DbContext (namespace System.Data.Entity dentro do assembly EntityFramework.dll). E implemente-o conforme o código abaixo:

05

Caso o banco de dados não exista, e nenhuma string conexão tenha sido fornececida, então será criada uma base de dados local, cujo nome será igual a assinatura da classe dbcontext, isto é, o namespace da qual a classe pertence concatenado com o nome da classe dbcontext. Por exemplo, se sua classe dbcontext pertencer ao namespace “NomeDoCliente.NomeDoProjeto.Repositorio” e sua classe datacontext se chamar “ContextoBancoDados” então o nome de seu banco de dados será  “NomeDoCliente.NomeDoProjeto.Repositorio.ContextoBancoDados”… Não parece ser uma boa prática um nome deste tamanho com características de nomenclatura tão específicas, então recomendo que sempre seja informada uma string de conexão, como no exemplo anterior.

Obs.: Para este exemplo deixei a string de conexão fixa (“chumbada”) no código… Esta realmente não é uma boa prática, o melhor neste caso é deixar a string de conexão em um arquivo configurável de sua aplicação. Para este cenário procure utilizar recursos nativos, como os arquivos App.Config e Web.Config.

7 – Para garantir a criação de seu banco de dados no primeiro acesso procure deixar fixo em algum lugar estratégico de sua aplicação a chamada para o método de criação da base. Não é uma boa prática tornar esse bloco de criação do banco de dados algo que será sempre validado e executado, pois isso pode consumir tempo e recursos operacionais. Então, como dica, os dois locais que acredito serem os ideais para este tipo de procedimento:
– Evento Application Start do Global.asax – no caso de aplicações web.
– Método Main() do arquivo Program.cs – no caso de aplicações desktop e console.

Mais para frente, neste mesmo post, irei demonstrar os comandos necessários para criação do banco de dados.

8 – Para implementação do design pattern DAO e utilização do Entity Framework 4.1 implementaremos as classes RepositorioMontadora e RepositorioCarro dentro da pasta Data da seguinte forma:

060

070

Para encapsular os comandos de criação do banco de dados, encapsularemos seu comportamento em uma classe chamada BancoDadosRepositorio implementada por uma interface chamada IFonteDadosRepositorio, conforme o código a seguir:

090

080

9 – Agora que temos criadas nossas entidades e nossos repositórios, poderemos implementar nossa classe controller que irá gerenciar os acessos as nossas fontes de dados, além de fazer ponte com nossa camada de visão. Nesta classe, por conta da simplicidade de nosso exemplo, iremos implementar as regras de persistência das montadoras e dos carros no mesmo controller. Da seguinte maneira:

100

10 – Nesses momentos já temos nossa camada de DAO pronta, além das camadas model e controller (pertencentes ao MVC) também concluídas. O próximo passo agora é implementar a camada de visão. Para este exemplo criaremos uma aplicação console, pois no momento a estrutura de nossa aplicação tem maior relevância do que a interface. Nesta demonstração criamos uma aplicação console chamada SampleConsole, e fizemos referência para o projeto SampleCore, para que conseguíssemos acessar suas classes. Nossa aplicação console deverá se parecer com algo como:

110

A estrutura da aplicação deve ficar como a imagem a seguir:

00000

Para fazer o download acesse este link: http://code.msdn.microsoft.com/Entity-Framework-41-MVC-DAO-4860e78c

Por
Fernando Henrique Inocêncio Borba Ferreira.

Windows Phone Mango e Microsoft SQL CE

Para armazenar e recuperar dados em um banco de dados local as aplicações Windows Phone utilizam LINQ to SQL. O LINQ to SQL é um recurso nativo do Framework 3.0 e foi um dos recursos que mais chamaram atenção no lançamento do Microsoft Visual Studio 2008. O LINQ to SQL, como já dito em outros posts, fornece mapeamento objeto-relacional entre a aplicação e bancos de dados relacionais, além disso é um recurso extremamente poderoso, que permite a construção de consultas utilizando sintaxe C# e VB.Net.

O Windows Phone Mango utiliza como base de dados o Microsoft SQL CE, versão compacta do famoso banco de dados Microsoft SQL, e própria para dispositivos móveis.

Aqui vamos apresentar o exemplo de uma aplicação que armazena e remove dados do banco de dados Microsoft SQL CE, utilizando como plataforma o Windows Phone Mango.

1o – Crie a aplicação utilizando o template Windows Phone Application.

2o – Ao ser perguntado sobre a versão da plataforma Windows Phone, selecione a opção Windows Phone OS 7.1.

3o – Dentro do projeto crie três pastas, sendo elas: DAO, Controller e Model.
windowsPhone01

4o – Faça referência a DLL System.Data.Linq.
windowsPhone02

5o – Dentro da pasta Model, criada anteriormente, crie a classe DataItem conforme a imagem a seguir.
windowsPhone03

6o – Adicione os atributos de mapeamento objeto-relacional LINQ para criar o mapeamento entre a classe e a tabela do banco de dados do Microsoft SQL CE. Faça referência ao namespace System.Data.Linq.Mapping.
windowsPhone04

7o – Dentro da pasta DAO crie uma classe chamada DataBaseContext, e a faça herda DataContext, classe presente no namespace System.Data.Linq. Esta classe será nosso data context e será responsável por fazer a ponte entre a aplicação e o banco de dados. Dentro da classe crie um atributo público chamado DataItems e que seja do tipo Table<DataItem>, este atributo representará nossa tabela no banco de dados. A classe DataBaseContext deverá se parecer com a seguinte implementação:
windowsPhone05

8o – Agora que temos nossa entidade e nosso data context, devemos criar uma classe que encapsule os comando com o banco de dados, por isso criaremos dentro da pasta DAO a classe DAOProvider. Esta classe representará nossa camada de acesso a dados e encapsulará os comandos feitos para o banco de dados. Nesta classe implementaremos quatro métodos, sendo eles: CreateDataBase, método que criará a base de dados; GetDataItems, método que retornará todos os dados que estiverem no banco de dados; Save, salva novos registros na base de dados; Remove, remove os dados do banco de dados. A implementação funcionará da seguinte forma:
windowsPhone06

9o – Para intermediar as chamadas entre a camada de visão e o repositório criaremos uma classe de controle que faça chamadas ao repositório. A vantagem de utilizar este tipo de classe é a possibilidade de encapsultar o repositório e poder adicionar filtros que intermediem o acesso aos dados do banco de dados. Esta classe deverá ser implementada como demonstrado a seguir:
windowsPhone07

10o – Finalmente vamos construir a interface do nosso aplicativo. Esta será uma interface bastante simples, deverão ser adicionados os seguintes itens: um textbox, um listbox e um botão (mais detalhes do layout poderão ser vistos no link para o download do exemplo, pois o layout do projeto não é o objetivo deste post).
windowsPhone08

11o – O único detalhe importante do layout é o modo como será feito o bind do listbox, pois na verdade ele será populado "na mão", isto é, os itens serão adicionados um-a-um (em um próximo post veremos como fazer isso de modo automático). Segue detalhe do XAML descrevendo o bind do listbox.
windowsPhone09

12o – A lógica da camada de visão deverá funcionar como o código apresentado a seguir. Como pode ser observado no código, ao clicar no botão Salvar um novo registro será incluso na base de dados, e ao clicar sobre qualquer item do listbox, o mesmo será removido do banco de dados.
windowsPhone10

Esta é uma introdução ao acesso a dados utilizando o Windows Phone e o Microsoft SQL CE. Espero que este post sirva como introdução para todos, e também espero que motive a construção de novos aplicativos para esta nova plataforma.

Para o download do exemplo acesse esse link: http://code.msdn.microsoft.com/Windows-Phone-Mango-e-SQL-81f15d55

[]s!

windowsPhone11

Atualizando dados utilizando o método Attach!!!!

O modo mais fácil de atualizarmos dados de nosso modelo no banco de dados é através do método Attach. Assim como utilizamos o InsertOnSumit para executarmos inclusões na base de dados, o método Attach pode ser bastante útil para atualizações de nossas entidades em nossas bases de dados.

Vamos supor uma classe chamada Arquivo:

AttachArquivo01

… e vamos utilizar uma data context como o seguinte:

AttachDataContext02

Em seguida, vamos criar um método para submeter nossas atualizações ao banco de dados:

AttachSalvar03

Observe que caso o valor de nossa propriedade Id seja distinto de ZERO, teremos de executar uma consulta na base de dados para retornar a instância que desejamos e assim fazermos o “de/para” dos dados de nossa instância (com valores atualizados) para a instância vinda do banco de dados.

Se utilizássemos o método Attach iríamos reduzir a complexidade deste código e removeríamos uma consulta desnecessária ao banco de dados para buscar a instância que lá existe, desta maneira:

AttachSalvar04

Simples! Veja que a complexidade do código foi reduzida e eliminamos uma consulta extra ao banco de dados, o que acaba gerando uma rotina de atualização mais rápida e performática.

Mas existe uma ressalva sobre este método: o Attach EXIGE que a instância de objeto passada por parâmetro não esteja vinculada a nenhum outro Data Context, isto é, caso a instância de objeto passada por parâmetro para o método Salvar tenha vindo diretamente de um Data Context, o attach não ocorrerá, e receberemos uma mensagem de erro, por isso, neste caso, a classe Arquivo implementa a interface ICloneable, resultando nesta estrutura:

AttachArquivo05

[]s e até a próxima! =]

 

Por
Fernando Henrique Inocêncio Borba Ferreira.