c
| Por Luciano Caixeta Moreira luciano.caixeta@braziltradenet.gov.br Luciano Caixeta é desenvolvedor .NET e possui as certificações MCSD .NET, MCDBA e MCT. Luciano mantém um blog no TheSpoke em http://br.thespoke.net/MyBlog/Luti/MyBlog.aspx. |
|
|
|
|
| Controle a versão das tabelas no SQL Server (Parte 1) | |
|
|
|
Trabalhei em um projeto com smart client que será distribuído e utilizado por prestadores de serviço em todo o Brasil. Como o projeto deve funcionar sem conexão constante com a internet, um dos requisitos de sistema é que ele deve manter uma série de informações no cliente e a possibilidade de atualizar essas tabelas, quando houver conexão com a internet.
Para que o cliente não fique continuamente fazendo download de tabelas com as mesmas informações que as locais, é necessário um mecanismo de controle de versão das tabelas. Com esse mecanismo, um cliente pode verificar se está com uma versão atualizada e, caso não esteja, a atualização da tabela é efetuada.
Como a funcionalidade do software é muito específica, ele somente precisa armazenar em torno de 20 tabelas de apoio que não mudam com muita freqüência, fazendo com que a solução seja adequada para o problema. Além dessas tabelas existem outras informações que serão entradas pelo cliente e depois consolidadas no servidor central através de web services, mas essas não necessitam do controle de versão.
Dado o cenário, vamos aos passos para se montar uma solução completa.
Controlando a versão de suas tabelas
O script abaixo é responsável por criar algumas tabelas e montar todo o esquema de manutenção de versão. A solução escolhida foi utilizar uma tabela de controle de versão que é atualizada através de triggers, toda vez que uma tabela é modificada.
Para que o script funcione, o SQL Server deve possuir a base Northwind, pois é de lá que são retiradas as informações para as tabelas criadas. Note também que a criação da base theSpoke está comentada, então você pode colocar as tabelas no banco de dados que julgar conveniente.
=========================================
/*
USE Master
CREATE DATABASE theSpoke
*/
USE theSpoke
GO
/*
Cria as tabelas que serão utilizadas
*/
IF exists (SELECT * FROM dbo.sysobjects WHERE [ID] = object_id('Categoria')
and OBJECTPROPERTY(id, 'IsUserTable') = 1)
DROP TABLE Categoria
GO
CREATE TABLE Categoria
(
Codigo INT IDENTITY NOT NULL PRIMARY KEY,
Nome NVARCHAR(15) NOT NULL,
Descricao ntext NULL
)
GO
IF exists (SELECT * FROM dbo.sysobjects WHERE [ID] = object_id('Fornecedor')
and OBJECTPROPERTY(id, 'IsUserTable') = 1)
DROP TABLE Fornecedor
GO
CREATE TABLE Fornecedor
(
Codigo INT IDENTITY NOT NULL PRIMARY KEY,
NomeEmpresa NVARCHAR(40) NOT NULL,
NomeContato NVARCHAR(30) NULL
)
GO
IF exists (SELECT * FROM dbo.sysobjects WHERE [ID] = object_id('Produto')
and OBJECTPROPERTY(id, 'IsUserTable') = 1)
DROP TABLE Produto
GO
CREATE TABLE Produto
(
Codigo INT IDENTITY NOT NULL PRIMARY KEY,
Nome NVARCHAR(40) NOT NULL,
Categoria INT NULL,
Preco MONEY NULL
)
GO
/*
Insere as informações existentes no banco de dados
Northwind
*/
INSERT INTO Fornecedor
SELECT CompanyName, ContactName
FROM Northwind..Suppliers
INSERT INTO Categoria
SELECT CategoryName, Description
FROM Northwind..Categories
INSERT INTO Produto
SELECT ProductName, CategoryID, UnitPrice
FROM Northwind..Products
SELECT * FROM Fornecedor
SELECT * FROM Categoria
SELECT * FROM Produto
/*
Cria a tabela de controle de versão e as triggers
responsáveis por manter a informação de versão.
*/
IF exists (SELECT * FROM dbo.sysobjects WHERE [ID] = object_id('ControleVersao')
and OBJECTPROPERTY(id, 'IsUserTable') = 1)
DROP TABLE ControleVersao
GO
CREATE TABLE ControleVersao
(
NomeTabela VARCHAR(128),
DataAtualizacao DATETIME
)
GO
/*
Popula a tabela ControleVersao com a versão corrente
de todas as tabelas de usuário, menos a que controla as versões!
*/
INSERT INTO ControleVersao
SELECT [Name], GETDATE()
FROM SysObjects
WHERE XType = 'U'
AND Name <> 'ControleVersao'
-- Verifica se estão todos os registros na tabela
SELECT * FROM ControleVersao
GO
/*
São as triggers que garantem a atualização da tabela de
versão quando um registro é incluido, excluído ou alterado.
*/
CREATE TRIGGER TRG_Fornecedor
ON Fornecedor
FOR INSERT, UPDATE, DELETE
AS
UPDATE ControleVersao
SET DataAtualizacao = GETDATE()
WHERE NomeTabela = 'Fornecedor'
GO
CREATE TRIGGER TRG_Categoria
ON Categoria
FOR INSERT, UPDATE, DELETE
AS
UPDATE ControleVersao
SET DataAtualizacao = GETDATE()
WHERE NomeTabela = 'Categoria'
GO
CREATE TRIGGER TRG_Produto
ON Produto
FOR INSERT, UPDATE, DELETE
AS
UPDATE ControleVersao
SET DataAtualizacao = GETDATE()
WHERE NomeTabela = 'Produto'
GO
=========================================
Uma vez criado os mecanismos, toda atualização nas tabelas de apoio registra uma nova versão na tabela de controle. Faça os testes executando os comandos abaixo e verificando as alterações na tabela ControleVersao.
INSERT INTO Fornecedor VALUES ('Argos', 'Luciano Caixeta Moreira')
UPDATE Categoria SET Nome = 'Bebida' WHERE Codigo = 1
DELETE FROM Produto WHERE Codigo = 1
Esta é uma maneira de controlar as versões das suas tabelas no servidor, apenas utilizando o SQL Server. Caso você não queira que algumas tabelas façam parte do processo de versionamento, apenas deixe de criar as respectivas triggers e exclua os registros da tabela de controle.
Não encontrei meios de verificar a data de última atualização das tabelas utilizando as tabelas de sistema do SQL Server, procurei em sysobjects, sysindexes, sys... Se alguém souber de algum controle desse tipo feito pelo SQL Server, a solução será bem mais fácil e eficiente.
É importante ressaltar que esse controle só é interessante para tabelas de tamanho pequeno, pois tabelas gigantes precisam de um controle diferenciado, baseado em versões de ranges de chaves ou outro mecanismo qualquer.
Baixe aqui o script VersaoTabelas.sql
Na segunda parte do artigo demonstrarei como o cliente pode comparar as versões de suas tabelas e atualizar os dados.