diretor técnico - the club · do banco de dados passando ... join sys.query_store_plan as p ......

24

Upload: truongkhuong

Post on 18-Jan-2019

213 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo
Page 2: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Caro leitor,

Preparamos para você este mês, uma revista cheia de novidades contendo os principais assuntos no mundo da

programação. Para iniciar nossa série de artigos, nosso colaborador Ricardo Barbosa Crivelli redigiu o assunto sobre a

tecnologia “AngularJS”, com o título “AngularJS - Usando servicos para compartilhar informacoes entre dois

controladores”. Ele nos ensina que os servicos são objetos denominados “singleton”, ou seja, que são instanciados somente

um por aplicação e são carregados somente quando forem necessários (método conhecido como lazy-load) e são

utilizados para manter a informação durante o ciclo de vida da aplicação. Já nosso colunista mensal Hamden Vogel

escreveu o artigo “Threads – Técnicas turbinadas e recursos interessantes de envio de e-mails via GMAIL”. Nesta primeira

parte ele implementa a classe “TProgressThread”, que seria a própria thread utilizada para medir o tempo de algum

processo. Artigo recomendável para o programador Delphi. Já nosso consultor Thiago Cavalheiro Montebugnoli abordou

um assunto relacionado ao Entity Framework no artigo “Entity Framework – Trabalhando com Transacoes”. Neste tutorial

ele cria um exemplo prático envolvendo entidades com mais de um modelo de dados utilizando a classe

“TransactionScope”. No outro artigo escrito por ele, chamado “Principais recursos do microsoft SQL Server 2016”, como o

próprio nome já diz, foi ressaltada as principais novidades deste poderoso Banco de Dados da Microsoft.

Desejo uma ótima leitura.

Um abraço!

Marcos César Silva

Diretor Técnico

Editorial

Page 3: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Principais recursos do Microsoft SQL Server

2016

No artigo deste mês irei explorar alguns recuros do lançamento da nova versão do Banco de Dados da Microsoft,

o Microsoft SQL Server 2016. Terei como base o E-Book gratuito escrito por Stacia Varga, Denny Cherry E Joseph D’

Antoni que está disponível no formato “pdf” no seguinte link: http://aka.ms/IntroSQLSvr2016PE_dsktp_pdf

É importante informá-los que o lançamento oficial foi no dia 07 de Abril de 2016 e sua versão “SQL Server

2016 Release Candidate 2” poderá ser baixada e instalada através do link: https://www.microsoft.com/pt-

br/evalcenter/evaluate-sql-server-2016

A ideia central deste artigo será de apenas apontar e explorar algumas novidades encontradas nesta nova versão

do banco de dados, sempre tendo como base o E-book supracitado, ou seja, não abordarei instalações, configurações,

entre outros recursos que explorarei com certeza em artigos futuros.

Segurança mais rígida O Microsoft SQL Server 2016 introduz diversos novos recursos relacionados à segurança de dados, sendo:

“Always Encrypted“, “Row-Level Security” e “Dinamic Data Masking”. Abaixo irei descrever todos estes recursos.

- Always Encrypted

Traduzindo para o português como “Sempre Crptografados”, é denominado como uma tecnologia de

criptografia do lado do cliente no qual os dados são automaticamente criptografados não apenas quando é escrito, mas

também quando ele é lido por um outro aplicativo. Ao contrário de criptografia de dados transparente, que criptografa

os dados no disco. Sua principal característica ao utilizar este tipo de controle, é que a aplicação transfere de forma

segura os dados criptografados no banco de dados que pode ser descriptografado depois apenas por um aplicativo

que tem acesso à chave de criptografia.

Exemplo:

CREATE TABLE dbo.EXEMPLO_CRIPTOGRAFIA

(

CODIGO INT IDENTITY(1,1) PRIMARY KEY

NOME VARCHAR(50),

DOCUMENTO VARCHAR(30),

DATA_NASCIMENTO DATE ENCRYPTED WITH

(

ENCRYPTION_TYPE = RANDOMIZED,

ALGORITHM = ‘AEAD_AES_256_CBC_HMAC_SHA_256’,

COLUMN_ENCRYPTION_KEY = MINHA_CHAVE

),

TIPO CHAR(10) ENCRYPTED WITH

(

ENCRYPTION_TYPE = DETERMINISTIC,

ALGORITHM = ‘AEAD_AES_256_CBC_HMAC_SHA_256’,

COLUMN_ENCRYPTION_KEY = MINHA_CHAVE

));

Page 4: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

No exemplo acima, na criação do campo definimos o tipo, o algoritmo e a chave de criptografia. Utilizamos nos

campos “DATA_NASCIMENTO” e “TIPO” através do comando “ENCRIPTED WITH”.

- Row-Level Security

Este tipo de recurso permite configurar tabelas de tal forma que os usuários vejam apenas as linhas dentro da

tabela para a qual iremos conceder acesso. A “Row-Level Security” permitirá aos DBAs e profissionais da área de banco

de dados, realizar um controle de acesso aos dados que estão armazenados em determinadas tabelas, através do uso

de funções conhecidas como “Predicate”, limitando assim que uma possível coluna e seu respectivo valor seja

consultado.

Poderemos usar um “predicate” para filtrar silenciosamente as linhas que são acessíveis pelo usuário ao usar

“INSERT”, “UPDATE” ou “DELETE”. Além disso, poderemos também usá-los para o usuário de gravar dados através das

cláusulas: “AFTER INSERT”, “AFTER UPDATE”, “BEFORE UPDATE” e “BEFORE DELETE”.

Exemplo:

CREATE SCHEMA Seguranca

GO

CREATE FUNCTION Seguranca.acessoUsuarioPredicate(@UserName sysname)

RETURNS TABLE

WITH SCHEMABINDING

AS

RETURN SELECT 1 AS accessResult

WHERE @UserName = SUSER_SNAME()

GO

CREATE SECURITY POLICY Seguranca.acessoUsuarioPolicy

ADD FILTER PREDICATE Seguranca.acessoUsuarioPredicate(UserName) ON dbo.Tabela,

ADD BLOCK PREDICATE Seguranca.acessoUsuarioPredicate(UserName) ON dbo.Tabela

GO

No código acima foi criado uma função para adicionar e bloquear um usuário em uma

determinada tabela.

- Dynamic data masking

O Dynamic Data Masking, limita a exposição de dados confidenciais, os mascarando para usuários não-

privilegiados. O Mascaramento de dados dinâmico ajuda a evitar o acesso não autorizado a dados confidenciais,

permitindo aos clientes designar o quanto os dados confidenciais para revelar com impacto mínimo na camada de

aplicação. É uma característica de segurança que esconde os dados no conjunto de resultados de uma consulta sobre

campos de banco de dados designado, enquanto os dados no banco de dados não são alterados. Considerado de fácil

utilização com aplicativos existentes, desde que as regras de mascaramento sejam aplicadas nos resultados da consulta.

Muitos aplicativos podem mascarar dados confidenciais sem modificar consultas existentes.

Exemplo:

CREATE TABLE PESSOAS

(

ID int IDENTITY PRIMARY KEY,

NOME varchar(100) MASKED WITH (FUNCTION = 'partial(1,"XXXXXXX",0)') NULL,

SOBRENOME varchar(100) NOT NULL,

FONE varchar(12) MASKED WITH (FUNCTION = 'default()') NULL,

Email varchar(100) MASKED WITH (FUNCTION = 'email()') NULL

);

Ao criar os campos na tabela PESSOAS poderemos incorporar algumas máscaras existentes nesta nova versão

do SQL Server, como por exemplo: “PARTIAL”, “DEFAULT” e “EMAIL”, ambas precedidas do comando “MASKED”.

Page 5: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Melhorias no Motor do Banco de Dados

No Microsoft SQL Server 2016, poderemos encontrar uma funcionalidade melhorada em todo o motor (engine)

do banco de dados passando a gerir mais de um número muito maior de bases de dados SQL Server por meio de seu

banco de dados como um serviço (DBaaS). Neste item, vamos explorar algumas das novas funcionalidades dos

denominados “Query Store” e “Stretch Database”.

- Query Store

Esta funcionalidade irá nos auxiliar em muito em nossas longas jornadas de análise de planos de execução, a

“Query Store” vai dar a possibilidade de fazer a análise de uma plano de execução que possa estar apresentando

problemas de desempenho através de uma “indicação” ou “orientação” por parte do SQL Server, podendo escolher um

plano de execução para processar uma query. Podemos considerar esta característica como uma das maiores melhorias para o motor de banco do dados SQL

Server, desde a introdução de pontos de vista de gerenciamento dinâmico. Podemos corrigir diversos tipos de

problemas acarretando uma maior velocidade dos dados.

Exemplo: Habilitando o “Query Store” sem parâmetros.

ALTER DATABASE dbTheClub SET QUERY_STORE = ON;

Exemplo: Habilitando o “Query Store” com parâmetros.

ALTER DATABASE dbTheCLub

SET QUERY_STORE = ON

(

OPERATION_MODE = READ_WRITE,

CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 5),

DATA_FLUSH_INTERVAL_SECONDS = 2000 ,

MAX_STORAGE_SIZE_MB = 10 ,

INTERVAL_LENGTH_MINUTES = 10

);

Exemplo de utilização do “Query Store”

SELECT TOP 10 rs.avg_duration,

qt.query_sql_text,

q.query_id,

qt.query_text_id,

p.plan_id,

GETUTCDATE() AS CurrentUTCTime,

rs.last_execution_time

FROM sys.query_store_query_text AS qt

JOIN sys.query_store_query AS q ON qt.query_text_id = q.query_text_id

JOIN sys.query_store_plan AS p ON q.query_id = p.query_id

JOIN sys.query_store_runtime_stats AS rs ON p.plan_id = rs.plan_id

WHERE rs.last_execution_time > DATEADD(hour, -1, GETUTCDATE())

ORDER BY rs.avg_duration DESC;

Na utilização de “Query Stores” teremos diversos tipos, como: query_store_query_text:

Texto da consulta digitado pelo usuário, incluindo espaços em branco, sugestões e comentários.

query_store_query: Informações de consulta e as suas estatísticas de execução.

query_store_plan: informações de plano de execução para consultas.

query_store_runtime_stats: estatísticas de tempo de execução para consultas.

Page 6: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

- Stretch Database

Esta é uma funcionalidade bastante esperada principalmente para os usuários do Azure, através do “Strech

Database”, em português ficaria mais ou menos como “Base de Dados de Estiramento”, será possível armazenar porções

(partes ou fatias) de uma tabela no “Azure SQL Database”. Através deste recurso, temos a capacidade de armazenar

dados históricos contidos em uma tabela de forma segura e transparente diretamente na nuvem, ou melhor dizendo no

Microsoft Azure. A partir do momento que este recurso é habilitado, de forma silenciosa os dados considerados

históricos são migrados para um banco SQL Azure, tudo isso é feito pelo SQL Server sem exigir qualquer alteração de

código em sua query ou aplicação.

Importante: Para realizar este teste é necessário possuir uma conta Azure.

Exemplo para configurar a opção “REMOTE DATA ARCHIVE”:

EXEC sp_configure 'remote data archive', '1';

GO RECONFIGURE;

GO

Ou também podemos facilmente configurar via interface gráfica, clicando com o botão direito sobre a base de dados escolhendo “Tasks” e logo em seguida “Enable Database for Stretch...” Ver Imagem 01.

Figura 01: Configurando o “Database for Stretch...”

Conclusões

Procurei neste artigo discorrer um pouquinho das principais novidades desta novíssima versão do Banco de

Dados SQL

Server. De acordo com minhas pesquisas e leituras de artigos, a própria Microsoft está muito confiante neste novo

banco, o mesmo está promentendo ser ainda mais robusto para aplicações de pequeno, médio e grande porte.

Page 7: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo para quem desejar obter

informações mais profundas sobre os assuntos abordados neste artigo, assim como outros inúmeros que poderão

encontrar lá com minuciosos detalhes.

Este é o primeiro de muitos artigos que a nossa equipe irá preparar para você.

Desejo a todos uma ótima leitura. Um abraço!

Referências

https://www.microsoft.com/pt-br/evalcenter/evaluate-sql-

server-2016 https://msdn.microsoft.com/en-

us/library/bb669076(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/mt130841.aspx

Sobre o Autor

Thiago Cavalheiro Montebugnoli, Adora aprender novas tecnologias. Formado pela Faculdade de Tecnologia de

Botucatu – SP (FATEC), já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Como experiências profissionais mais recentes, possui em seu currículo sua atuação no Centro de Processamento de Dados da Prefeitura

Municipal de Itaí-SP e atualmente compõe a equipe da Coordenadoria Tecnologia da Informação no IFSP – Instituto Federal do Estado de São Paulo em Avaré. Além disso, é colunista mensal da Revista The Club Megazine e é consultor Técnico do The Club. Possui as seguintes

certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certified Technology Specialist, MCAD - Microsoft Certified Application Developer e MCSD - Microsoft Certified Solution Developer.

E-mail: [email protected]

Page 8: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

AngularJS - Usando serviços para

compartilhar informações entre dois controladores

Introdução Até agora nós estávamos somente preocupados em como a view está amarrada com o $scope e como o controller

administra as informações. Para uma melhor performance os controllers são instanciados somente quando eles forem

necessários e são descartados quando eles não são.

O que são serviços? Os serviços são objetos singleton que são instanciados somente um por aplicação e são carregados somente quando

forem necessários (método conhecido como lazy-load). Eles são utilizados para manter a informação durante o ciclo de vida

da aplicação e transmiti-la de forma eficaz entre os controladores.

Código Inicial Vamos iniciar nosso artigo com uma página HTML básica que inclui dois arquivos Java Scripts, o com o framework e

o outro chamado de app.js com os códigos de nossa aplicação.

<!DOCTYPE html>

<html>

<head>

<title>The Club</title>

<script type="text/javascript"

src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></scrip

t>

<script type="text/javascript" src="app.js"></script>

</head>

<body>

<div ng-app="aplicacao">

<h1>Usando serviços para compartilhar informações entre dois

controladores</h1>

</div>

</body>

</html>

Neste exemplo nós estaremos criando um serviço para armazenar as mensagens e dois controles, um para renderizar

a lista das mensagens e outro para adicionar mais mensagens à lista.

Page 9: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Criando o módulo

Vamos criar um módulo chamado de mensagens.

/* Arquivo: app.js */

angular.module('aplicacao', []);

angular.module('aplicacao').factory('mensagens', function(){

});

O próximo passo é criar um objeto que vai carregar todas as dependências de nosso serviço e retorná-la sempre ao

final.

/* Arquivo: app.js */

angular.module('aplicacao', []);

angular.module('aplicacao').factory('mensagens', function(){

var mensagens = { };

return mensagens;

});

Feito isso vamos criar um objeto chamado de listaMensagens que vai conter inicialmente um vetor vazio. Esse vetor

vai servir para armazenar nossas mensagens.

angular.module('aplicacao', []);

angular.module('aplicacao').factory('mensagens', function(){

var mensagens = { };

mensagens.lista = [];

return mensagens;

});

A nossa próxima missão agora é criar um método que irá adicionar mensagens à nossa lista e para isso nós iremos

utilizar alguns métodos nativos, como o push que é utilizado para adicionar um elemento em um vetor e o método length que

retorna o tamanho do vetor, ou seja quantas mensagens estão armazenadas.

/* Arquivo: app.js */

angular.module('aplicacao', []);

angular.module('aplicacao').factory('mensagens', function(){

var mensagens = { };

mensagens.lista = [];

mensagens.adicionar = function(mensagem) {

mensagens.lista.push({

id: mensagens.lista.length,

texto: mensagem

});

}

return mensagens;

});

Page 10: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Criando os controladores Vamos criar os controladores que irão fazer uso de nosso módulo. Primeiro vamos criar o ListaController que irá

injetar nosso serviço mensagens e passar a lista para a view.

/* Arquivo: app.js */

angular.module('aplicacao', []);

[...]

angular.module('aplicacao').controller('ListaControlador', function (mensagens){

var self = this;

self.mensagens = mensagens.lista;

});

Agora vamos voltar ao nosso arquivo HTML e criar uma div que irá mostrar todas a nossa lista de mensagens.

<div ng-app="aplicacao">

<h1>Usando serviços para compartilhar informações entre dois

controladores</h1>

<div ng-controller="ListaControlador as listagem">

<p ng-repeat="mensagem in listagem.mensagens">

{{ mensagem.id }}: {{ mensagem.texto }}

</p>

</div>

</div>

A diretiva ng-repeat serve para iterar por nossa listagem dentro de nossa view e mostrar o conteúdo de cada

mensagem. Se você executar nosso código agora verá que a página continua em branco, já que nossa listagem está vazia.

Vamos criar um controlador chamado InsertControlador que irá injetar o nosso serviço mensagens. Ele irá conter também

um método chamado adicionaMensagem que usará a função adicionar criada em nosso serviço.

/* Arquivo: app.js */

angular.module('aplicacao', []);

[...]

angular.module('aplicacao').controller('InsertControlador', function

(mensagens){

var self = this;

self.adicionaMensagem = function(mensagem){

mensagens.adicionar(mensagem);

};

});

Page 11: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Vamos criar um formulário em nosso arquivo HTML para adicionarmos novas mensagens.

<div ng-controller="ListaControlador as listagem">

<p ng-repeat="mensagem in listagem.mensagens">

{{ mensagem.id }}: {{ mensagem.texto }}

</p>

</div>

<div ng-controller="InsertControlador as insert">

<form ng-submit="insert.adicionaMensagem(insert.mensagemPadrao)">

<input type="text" ng-model="insert.mensagemPadrao">

<button type="submit">Adicionar</button>

</form>

</div>

E para garantir que nós sempre tenhamos uma mensagem padrão para nossas mensagens declare a variável

mensagemPadrao em nosso controlador.

angular.module('aplicacao').controller('InsertControlador', function

(mensagens){

var self = this;

self.mensagemPadrao = 'The Club Megazine';

self.adicionaMensagem = function(mensagem){

mensagens.adicionar(mensagem);

self.mensagemPadrao = '';

};

});

Page 12: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Conclusão No artigo de hoje nós aprendemos como utilizar um serviço para trocar informações entre vários controladores. Este

foi um exemplo bem simples mas que mostra de forma bastante clara como devemos proceder em grandes aplicações. Um

abraço a todos e até a próxima!

Sobre o Autor

Ricardo Barbosa Crivelli, mais conhecido como Rico Crivelli, é formado como Bacharel em Sistemas de Informação e

Licenciado em Computação pela Universidade Estadual do Norte do Paraná, atualmente é Técnico em TI no Instituto Federal de São Paulo – Câmpus Avaré. Tem como especialidade a linguagem PHP e o framework Symfony, apesar de adorar trabalhar com front-end e

desenvolvimento mobile e possuir as certificações COBiT 4.1 Foundation e Delphi 2006 Developer.

E-mail: [email protected]

Page 13: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

ADO. NET Entity Framework - Trabalhando

com Transações

No artigo deste mês farei o uso da classe “TransactionScope” presente no Namespace “System.Transaction” e

do ADO.NET Entity Framework, uma das principais tecnologias de persistência de dados englobada na plataforma .NET.

Para o exemplo utilizarei como ferramenta de desenvolvimento o Microsoft Visual Studio junto com a linguagem C#.

ADO.NET Entity Framework

Antes de começarmos a desenvolver o artigo achei necessário realizar uma abordagem rápida sobre o conceito

de desta tecnologia. O Entity Framework é uma camada de negócios existente para automatizar as atividades de banco

de dados relacionados para a sua aplicação. Esta estrutura suporta o desenvolvimento de aplicações orientadas a dados

permitindo a modelar entidades, relacionamentos e lógica de negócios.

Classe TransactionScope

Esta classe presente no .NET Framework desde a versão 2.0, fornece uma maneira simples de marcar um bloco

de código como participante de uma transação. Como foi dito anteriormente, esta classe tem origem do Namespace

“System.Transaction” e do Assembly “System.Transactions.dll” e possui os principais Construtores e Métodos.

Construtores (Ver Tabela 01)

Nome

Descrição

TransactionScope()

Inicializa uma nova instância da classe

TransactionScope.

TransactionScope(Transaction)

Inicializa uma nova instância da classe

“TransactionScope” e define a transação

especificada como a transação de ambiente, de

modo que o trabalho transacional dentro do

escopo utilize essa transação.

TransactionScope(Transaction, TimeSpan)

Inicializa uma nova instância da classe

“TransactionScope” com o valor de tempo limite

especificado, e define a transação especificada

como a transação de ambiente, de modo que o

trabalho transacional feito no escopo use essa

transação.

Page 14: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Metodos (Ver Tabela 02).

Nome

Descrição

Complete()

Indica que todas as operações no escopo sejam concluídas com êxito.

Dispose()

Termina o escopo da transação.

Equals(Object)

Verifica se o objeto especificado é igual ao objeto atual.

GetHashCode()

Serve como a função de “hash” para um tipo específico.

GetType()

Obtém o Type (tipo) da instância atual.

ToString()

Retorna uma string que representa o objeto atual.

Criando o exemplo

Antes de iniciarmos o exemplo gostaria de fazer uma consideração importante quando trabalhamos com o Entity

Framework. Para projetos pequenos, com no máximo 100 entidades inseridas no mesmo Modelo (Model) não há a

necessidade de realizar o controle de transações, pois todas as atualizações feitas através do Entity Framework já

acontecem em uma transação, ou seja, se ocorrer algum erro antes que o método “SaveChanges” esteja concluído, o

“RollBack” é garantido. Atribuímos este tipo de controle como transação implícita. Portanto, para este artigo iremos supor uma situação a qual iremos utilizar dois Modelos com algumas Entidades

para testes, sendo “Model1” e “Model2”. Fiquem a vontade para criar projetos do tipo Windows ou Web, no nosso caso

específico foi criado um projeto do tipo “Windows Forms” contendo apenas um botão no formulário para fins de testes.

Ver Imagem 01.

Figura 01: Criando um projeto de exemplo.

Page 15: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Na “Solution Explorer” clique com o botão direito sobre o projeto escolhendo “Add” / “New Item...”. Em “Visual

C# Items” em “Data” iremos adicionar um Modelo do tipo “ADO.NET Entity Data Model” com o Nome como “Model1”

e logo em seguida adicionar algumas Entidades para o nosso exemplo (Neste artigo não nos aprofundaremos nesta

etapa, pois a mesma já foi abordada em outros artigos). Seguiremos estes mesmos passos para adicionar o “Model2”.

Ver Imagem 02.

Figura 02: Adicionando dois Modelos de Dados (Model1 e Model2).

O primeiro passo ao trabalhar com Transações seria adicionar a referência “System.Transaction”. Para isto

clique com o botão direito sobre a “solution” escolhendo “Add/References” e navegue até a opção

“System.Transactions”. Ver Imagem 03.

Page 16: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Figura 03: Adicionando o Namespace System.Transaction.

O passo seguinte seria adicionar o Namespace ao projeto:

.

.

using System.Transactions;

.

.

No evento “Click” do botão iremos codificar o exemplo que fará a inserção de dados em duas tabelas e modelos

distintos, sendo na “Categories” e na “Territories”. Estas duas tabelas estão presentes na Base de Dados “NorthWind”.

Ver Listagem abaixo comentada.

private void btnExecutar_Click(object sender, EventArgs e)

{

Primeiramento foi declarado uma variável do tipo booleana “finalizado” para indicar se a transação foi realizada

com sucesso e logo em seguida instanciaremos o Modelo 1 e o Modelo 2.

bool finalizado = false;

Entities1 db1 = new Entities1();

Entities2 db2 = new Entities2();

Dentro de um “Try/Finally“ iremos instanciar a classe “TransactionScope”, responsável por envolver o bloco de

código em uma transação.

Page 17: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

try

{

using(TransactionScope scope = new TransactionScope())

{

Nesta região iremos executar as tarefas pertinentes. No nosso caso irei inserir dados na tabela

Categories presente no “Model1”.

Categories categories = new Categories()

{

CategoryID = 1,

CategoryName = "The Club"

};

db1.Categories.Add(categories);

Já no “Model2” iremos inserir dados na tabela “Territories”.

Territories territories = new Territories()

{

TerritoryID = "98765",

TerritoryDescription = "Datasmart",

RegionID = 1

};

db2.Territories.Add(territories);

Até o momento todas as tarefas estão prestes a ser executadas no banco de Dados. Com o auxílio

do “Try/Catch” através do Método “SaveChanges” gravaremos as alterações realizadas no Contexto.

try

{

db1.SaveChanges();

db2.SaveChanges();

finalizado = true;

}

catch

{

finalizado = false;

}

A variável booleana “finalizado” indica se a transação foi realizada, sendo assim, faremos um “if”

para identificar se a mesma foi completada. O método “scope.Complete()” fará o “commit”.

if (finalizado)

{

scope.Complete();

}

}

Page 18: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Mostraremos uma mensagem informando ao usuário se a tarefa foi concluída ou não.

if (finalizado)

MessageBox.Show("Tarefa concluída com sucesso!");

else

MessageBox.Show("Ocorreu uma Exceção!");

}

Iremos liberar da memória os modelos usando o método “Dispose()”.

finally

{

db1.Dispose();

db2.Dispose();

}

}

O exemplo ficará idêntico ao da Imagem 04.

Figura 04: Exemplo em run-time.

Conclusões

Neste artigo procurei descrever o uso da classe “TransactionScope” junto com o “Entity

Framework”. O uso de transações é muito comum nos sistemas que necessitam “commitar” no banco de

dados múltiplas informações, devendo ser na totalidade completadas com sucesso. A classe

“TransactionScope” nos permite trabalhar exatamente desta maneira, utilizando vários modelos de dados

com um número grande de entidades.

Fica aí a dica, um abraço e até o mês que vem!

Page 19: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Referências

https://msdn.microsoft.com/pt-br/data/jj590134

http://www.entityframeworktutorial.net/what-is-entityframework.aspx

https://msdn.microsoft.com/pt-

br/library/system.transactions.transactionscope(v=vs.110).aspx

Sobre o Autor Thiago Cavalheiro Montebugnoli, Adora aprender novas tecnologias. Formado

pela Faculdade de Tecnologia de Botucatu – SP (FATEC), já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Como experiências profissionais mais

recentes, possui em seu currículo sua atuação no Centro de Processamento de Dados da Prefeitura Municipal de Itaí-SP e atualmente compõe a equipe da Coordenadoria Tecnologia da Informação no IFSP

– Instituto Federal do Estado de São Paulo em Avaré. Além disso, é colunista mensal da Revista The Club Megazine e é consultor Técnico do The Club. Possui as seguintes certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certified Technology Specialist, MCAD - Microsoft Certified Application

Developer e MCSD - Microsoft Certified Solution Developer.

E-mail: [email protected]

Page 20: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Threads – técnicas turbinadas e recursos interessantes de envio de emails via GMail –

parte I

Olá leitores, vamos neste artigo explicar coisas que nem sempre são utilizadas em aplicações do mundo real, como recursos thread-safe,

thread para acompanhamento de tempo, gerenciamento de threads via enfileiramento, thread para envio de email via conta GMail e gerenciamento

de recursos críticos compartilhados via classes TCriticalSection e TMultiReadExclusiveWriteSynchronizer.

Para que se importar com estas funcionalidades? Aplicações que utilizam recursos para gravação, como escrever dados em um objeto do tipo

TListBox ou TClientDataSet, arquivos do tipo TextFile ou envio de dados a banco de dados – todos eles podem operar bem no mesmo processo que a

sua aplicação – sua aplicação tem apenas uma thread, que é o seu form principal – e até aí então tudo bem. Porém imagine agora uma aplicação

multi-thread cujo cenário utilize concorrentemente estes recursos – e como agora são entre threads estes mesmos recursos passam a ser recursos

críticos pelo fatos de serem compartilhados entre si – e por isso sua aplicação agora precisa tratar o controle de acesso simultâneo a estes recursos,

senão sua aplicação poderá entrar em deadlock – e isso não é uma maneira legal de resolver os problemas – precisamos de uma solução satisfatória

que previna o acesso a mais de um escritor enquanto se já um outro escritor chegar primeiro. E portanto chegamos as classes citadas acima

TCriticalSection e TMultiReadExclusiveWriteSynchronizer, mas a segunda mencionada é melhor para o nosso cenário pelo fato da mesma não ficar

enfileirando as demais threads – apenas bloqueando o acesso de escrita enquanto já tiver sido iniciado por outra thread (múltipla leitura, escrita

exclusiva). Vamos iniciar o nosso artigo implementando a classe TProgressThread, que é a nossa thread utilizada para medir o tempo ilustrativamente de

algum processo – a classe TTimer não funcionada para ambientes multi-thread – precisamos “marcar” o tempo de outra forma – ou seja utilizando a função WaitForSingleObject da API Kernel32 do Windows para fatiar o tempo em ciclos pré-definidos, permanecendo em um

loop desta thread e sincronizando com o evento do sistema de tempos em tempos, algo como (onde 1000 significa 1000 milésimos de segundo =>

1 segundo => de 1 em 1 segundo a função executa =>):

“ while not Terminated do

if WaitForSingleObject(FTickEvent, 1000) = WAIT_TIMEOUT then

Synchronize(Form1.ShowProgress);”

Utilizamos também a função (também o Windows) CreateEvent para criar um evento do sistema com uma variável do tipo THandle (FTickEvent) para

a função WaitForSingleObject.

Desenhando nossa TProgressThread para medir o tempo das rotinas

Esta classe a ser explicada aqui é interessante. Permite mostrar o andamento de um trabalho, via multi-thread, e utilizados alguns componentes

da VCL, como objetos de TImage, TPanel (parent do TImage) e de TImageList. Este último contém as partes das figuras necessárias para a ilustração no

sentido horário, como pode ser visto abaixo:

Page 21: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Figuras de 1 a 5 – exemplo de implementação real via multi-thread da classe TProgressThread.

type

TProgressThread = class(TThread)

private

FTickEvent: THandle;

procedure FinishThreadExecution;

protected

procedure Execute; override;

public

constructor Create(CreateSuspended: Boolean);

destructor Destroy; override;

end;

Page 22: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

{ TProgressThread }

constructor TProgressThread.Create(CreateSuspended: Boolean);

begin

inherited;

FreeOnTerminate := True;

FTickEvent := CreateEvent(nil, True, False, nil);

Synchronize(Form1.ShowPanelProgress);

end;

destructor TProgressThread.Destroy;

begin

CloseHandle(FTickEvent);

inherited;

end;

procedure TProgressThread.Execute;

begin

MyCS.Enter;

try

while not Terminated do

if WaitForSingleObject(FTickEvent, 100) = WAIT_TIMEOUT then

Synchronize(Form1.ShowProgress);

finally

MyCS.Leave;

end;

end;

procedure TProgressThread.FinishThreadExecution;

begin

Synchronize(Form1.HidePanelProgress);

Form1.ProgressImagePanel.Visible := False;

Terminate;

SetEvent(FTickEvent);

end;

Com isso vimos acima um trecho do código-fonte responsável por essa implementação. Podemos associar esta classe, que é uma thread, para

ser chamada em outras threads, e assim sendo a ilustração de progresso se mostrará com perfeição entre as execuções dos processos, até que seja

encerrado explicitamente pelo método FinishThreadExecution – esse método também poderá ser sincronizado

(Synchronize(Self.FinishThreadExecution)) para que a animação de progresso seja fechada com sucesso. Segue abaixo as funções de sincronização

chamadas pela classe TProgressThread, que deverão ser incluídas em algum formulário (recomendável o formulário em que está sendo chamado a

thread):

procedure TForm1.FormCreate(Sender: TObject);

begin

ProgressImagePanel.DoubleBuffered := True;

ProgressImages.GetBitmap(0, ProgressImage.Picture.Bitmap);

end;

procedure TForm1.ShowProgress;

begin

ProgressImages.Tag := (ProgressImages.Tag + 1) mod ProgressImages.Count;

ProgressImages.GetBitmap(ProgressImages.Tag, ProgressImage.Picture.Bitmap);

ProgressImage.Refresh;

end;

procedure TForm1.HidePanelProgress;

begin

ProgressImagePanel.Visible := False;

end;

procedure TForm1.ShowPanelProgress;

begin

ProgressImagePanel.Visible := True;

end;

Page 23: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Assim sendo, esta thread será chamada em outras threads, e quando o processamento dela estiver pronta chamaremos o método

FinishThreadExecution dela, como já dito anteriormente. Não tem coisa melhor que mostrar na prática em um exemplo real, e por isso vamos agora ilustrar uma maneira realmente interessante,

que é o envio de emails a partir de uma lista, utilizando então esta thread. Vamos discorrer sobre outra thread, a TSendMailThread. Enviando Emails

Vamos abordar daqui pra frente o processo de envio de emails pelo Delphi, de uma forma prática e independente de aplicativos como

Outlook, etc; será uma forma feita exclusivamente por componentes de terceiros do Delphi. Explicações Iniciais

Não vamos de cara mostrar os fontes de como mandar email sem antes configurar o ambiente, porque não é só isso; além de instalar certos

componentes tem que distribuir Dll´s em diretórios do Windows também. Acompanhando tudo desde o início é a melhor forma para aprendizado, e

até para fazer um “deploy” do produto é importante (você pode criar uma rotina automatizada para copiar as dll´s necessárias do Indy para o diretório

do Windows, por exemplo). Então vamos configurar uma estrutura para que possa enviar emails a partir de uma conta do GMail, chamada pelo Delphi,

em um ambiente multi-thread. A thread TSendMailThread terá esse objetivo.

Instalação do ambiente

As configurações se referem ao compilador Delphi 7. É altamente recomendável também migrar a versão dos componentes Indy. A versão

utilizada foi a 10. Site oficial do Indy: http://www.indyproject.org/Sockets/Download/svn.EN.aspx

Então vamos abordar as principais características relevantes:

1. Baixar pelo SVN (https://svn.atozed.com:444/svn/Indy10) userId “Indy-Public-RO” e sem senha todo o fonte do Indy10 para seu

computador;

2. Instalar os pacotes necessários necessariamente nesta mesma ordem informada abaixo (favor referir-se a documentação ou proceder

conforme abaixo);

Compilar (e sem instalar, apenas compilar!) IndySystem70.dpk (subdiretório Lib\System);

Compilar (e sem instalar, apenas compilar!) IndyCore70.dpk (subdiretório Lib\Core);

Compilar (e sem instalar, apenas compilar!) IndyProtocols70.dpk (subdiretório Lib\Protocols);

3. Agora instalar os pacotes dclIndyCoreX7.bpl e dclIndyProtocolsX7.bpl necessariamente nesta ordem; qualquer problema consultar o site

http://www.indyproject.org/Sockets/Docs/Indy10Installation.EN.aspx;

4. Mapear no Delphi em Library Path (Tools/Environment Options) para que sejam localizados os fontes do Indy, na ordem abaixo:

caminhodaInstalação\trunk\Lib\System;

caminhodaInstalação\trunk\Lib\Core;

caminhodaInstalação\trunk\Lib\Protocols;

5. Distribuir as dll´s libeay32.dll e a ssleay32.dll para “c:\windows\SysWOW64” (64 Bits)

ou “c:\windows\System32” (32 Bits). Provavelmente será a de 64. Elas podem ser baixadas no link (fiz upload pro meu FTP) em

http://hvogel.com.br/temp/dlls.rar;

1. Obviamente, possuir uma conta no GMail; é como se o próprio GMail enviasse os emails; se olhar nos itens enviados percebe-se que os emails

estão lá. Na verdade nosso programa “simula” esta operação, pois na verdade essa operação é endereçada para os serviços do servidor smtp

(Simple Mail Transfer Protocol – protocolo padrão para envio de e-mails através da Internet) do GMail (smtp.gmail.com);

2. Na conta do GMail acessar o ícone de configurações ( ) localizado no canto superior direito, e selecione em

“Configurações”. Então selecione a tab “Encaminhamento e POP/IMAP” e selecione “Ativar IMAP” na seção “Acesso ao IMAP”;

3. Acessar o recurso do GMail de habilitar aplicações com menos segurança para acessar ele. Acesse o link

“https://www.google.com/settings/security/lesssecureapps” e clique em “turn on” para manter ele ativado.

Demais configurações nossa aplicação proverá de dentro do fonte, para que seja instanciada as classes relevantes do Indy para o seu correto

acesso em tempo de execução (como por exemplo as classes TIdSMTP, TIdMessage e TIdSSLIOHandlerSocketOpenSSL) e demais configurações

relevantes, como número da porta do servidor (465) e é claro, o usuário e senha corretamente especificados (o usuário é no formato

usuá[email protected]). Podemos especificar que passaremos um texto no formato HTML que será felizmente renderizado neste formato – uma

observação no que diz respeito a imagens – o GMail bloqueia imagens recebidas – a única exceção são imagens já contidas em algum servidor. Não

adianta imagens linkadas de dentro do seu computador ou convertidas como codificação formato Base64 – vai bloquear do mesmo jeito. A solução

como dita anteriormente é referenciar as imagens a algum site que já contenha essas imagens já armazenadas (exemplo:

http://hvogel.com.br/img/lupa.png). A última observação é a utilização do formato MIME (MultiPurpose Internet Mail Extensions) que define o

formato das mensagens de correio eletrônico utilizando o protocolo SMTP já mencionado anteriormente.

Page 24: Diretor Técnico - The Club · do banco de dados passando ... JOIN sys.query_store_plan AS p ... Aproveito para indicar fortemente a leitura do e-book citado no ínicio do artigo

Conclusão

Vimos a configuração básica e essencial para que seja construída em cima disso uma aplicação funcional multi-thread cujo arcabouço foi

definido no escopo deste artigo. A próxima continuação vai discorrer sobre as classes thread mencionadas aqui juntamente com a continuação do

tema do envio de emais via conta do GMail. Demos muito foco sobre a correta configuração desde a instalação dos arquivos e dll´s e a compilação

destes artefatos nos locais corretos e adequados para uma correta execução desta rotina interessante de envio de emails. Vale ressaltar que é muito

difícil, árduo e cansativo encontrar tudo isso na internet; são encontradas informações muito mal explicadas e apenas em parte, bem como informações

obsoletas e incompletas – foi o que levou a discorrer sobre este tema, bem como a necessidade própria de escrever esta funcionalidade para um

amigo em particular que me fez também interessar sobre esta função de envio de emails.

Continuaremos em detalhes mais minuciosos, passo a passo, para um eficiente aplicativo profissional multi-thread que enviará emails

coletados em um banco de dados nosso. Não percam, será muito interessante e a ideia já antepasso a informação que é inovadora. Os fontes também

serão entregues juntos. Não percam a próxima edição e enquanto isso instalem de forma cuidadosa, todo o ambiente descrito acima nas informações

repassadas.

Até a próxima.

Sobre o Autor

Hamden Vogel Consultor TheClub

E-mail: [email protected]