![]() |
||||||||
|
|
||||||||


| com exemplos em VB |
| Componente para deixar forms em Vb semelhantes às telas do winnamp |
| Componente para colocar sua aplicação VB no Systray |
| Componente para transformar sua aplicação VB em serviço |
| Ferramentas úteis para quem usa Olap Server |
| |

|
|
Pesquisa personalizada
Manipulação de Disco Transacional com o Windows Vista Introdução Ainda não temos o WinFS, mas o Windows Vista nos trouxe recursos para fazermos a manipulação de disco de forma transacional. Isso é um grande avanço, podermos envolver a manipulação de arquivos dentro de nossas transações de negócio. O responsável por permitir isso no Windows Vista é o KTM - Kernel Transaction Manager. Ao contrário do que o nome diz, o KTM não roda apenas em Kernel Mode, este é apenas o nome das APIs para realizarem esta tarefa. Ao invés de permitir que as APIs tradicionais de manipulação de arquivos atuem de forma transacional, o que foi feito no KTM foi duplicar as APIs. Ou seja : Tinhamos uma createFile agora temos também uma createFileTransacted e assim por diante. Isso a principio faz com que as classes gerenciadas tradicionais para manipulação de arquivos não consigam aproveitar o recurso da manipulação de arquivos de forma transacional. Mas apenas a principio. Ocorre que um dos overloads da classe fileStream permite que já seja recebido o handle de um arquivo. Isso nos permite integrar o trabalho do KTM facilmente com as aplicações .NET, utilizando classes gerenciadas para a manipulação de arquivos.
Objetivo Demonstrar que podemos utilizar facilmente as transações de disco no ambiente gerenciado fazendo uso de uma classe auxiliar para gerenciar tais transações, o que nos permite inclusive manter nossas aplicações compatíveis com outras versões do Windows, como o XP. O KTM e as Transações Existem 2 formas de lidarmos com as transações do KTM : Podemos abrir e fechar as transações diretamente com as API's do KTM ou podemos utilizar transações gerenciadas e incluir as manipulações do KTM dentro das transações gerenciadas.
Neste artigo pretendo demonstrar que através do uso de uma classe auxiliar, podemos tornar o uso do KTM tão simples quanto o System.Transactions e com síntaxe semelhante, com a vantagem de ser mais leve. Mas não se antecipe, aguarde a conclusão final. A classe auxiliar
Utilizando uma transação do KTM Para termos idéia do que estamos falando, veja o código para o uso de uma transação do KTM :
Dim tx As IntPtr = DiscoTransacional.CreateTransaction(IntPtr.Zero, _ IntPtr.Zero, 0, 0, 0, Nothing, Nothing)
If DiscoTransacional.DeleteFileTransacted("E:\Users\Dennes\Documents\Test.txt", tx) _ Then
If Confirmar() Then DiscoTransacional.CommitTransaction(tx) Else DiscoTransacional.RollbackTransaction(tx) End If Else DiscoTransacional.RollbackTransaction(tx) End If DiscoTransacional.CloseHandle(tx)
Utilizando uma transação simplificada do KTM Agora, utilizando nossa classe DiscoTransacional, podemos utilizar o pattern using para garantir a finalização da transação. Observe como o código abaixo fica semelhante a uma transação realizada com o TransactionScope.
Using tr As New libTransacao.DiscoTransacional tr.AbrirTransacao() tr.DeletarArquivo("E:\Users\Dennes\Documents\Test.txt") If Confirmar() Then tr.Commit() End If End Using
Observe que utilizamos os membros de instância da classe DiscoTransacional Utilizando uma transação com o DTC Neste caso utilizamos o próprio TransactionScope para iniciar a transação. Fazemos uso dos métodos shared de nossa classe, DiscoTransacional. Esses métodos vão identificar a transação do DTC e fazer com que a execução da tarefa seja feita dentro da transação do DTC.
Using tr As TransactionScope = New TransactionScope() libTransacao.DiscoTransacional.DeletarArquivoDTC("E:\Users\Dennes\Documents\Test.txt") If Confirmar() Then tr.Complete() End If End Using Como a classe não precisa manter handle da transação e não é a responsável pelo commit nem rollback, neste exemplo utilizamos os membros shared da classe DiscoTransacional É interessante observarmos o código de como o método DeletarArquivoDTC consegue fazer sua tarefa dentro da transação do DTC :
If IsNothing(Transaction.Current) Then Throw New ApplicationException("Não existe transacao") End If Dim kt As IKernelTransaction Dim handle As IntPtr kt = TransactionInterop.GetDtcTransaction(Transaction.Current) kt.GetHandle(handle) DeleteFileTransacted(NomeArquivo, handle)
Compatibilidade com o ambiente do Windows XP
A Classe DiscoTransacional
Declarações públicas e DLLImports 10 Public Const FILE_ATTRIBUTE_NORMAL = &H80 11 Public Const GENERIC_READ = &H80000000 12 Public Const GENERIC_WRITE = &H40000000 13 Public Const CREATE_ALWAYS = 2 14
15 #Region "Declarações shared" 16
17 #Region "Transacao" 18 'APIs para o controle transacional 19
20 <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ 21 Public Shared Function CloseHandle(ByVal handle As IntPtr) As Boolean 22 End Function 23
24
25 <DllImport("Ktmw32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ 26 Public Shared Function CommitTransaction(ByVal transaction As IntPtr) As Boolean 27 End Function 28
29 <DllImport("Ktmw32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ 30 Public Shared Function RollbackTransaction(ByVal transaction As IntPtr) As Boolean 31 End Function 32
33 <DllImport("Ktmw32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ 34 Public Shared Function CreateTransaction( _ 35 ByVal securityAttributes As IntPtr, _ 36 ByVal guid As IntPtr, ByVal options As Int32, ByVal isolationLevel As Int32, _ ByVal isolationFlags As Int32, _ ByVal milliSeconds As Int32, ByVal description As String) As IntPtr 37
38 End Function 39 #End Region 40
41 #Region "Declaracoes de APIs para arquivos" 42 <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ 43 Public Shared Function DeleteFileTransacted(<MarshalAs(UnmanagedType.LPWStr)> _ ByVal file As String, _ 44 ByVal transaction As IntPtr) As Boolean 45 End Function 46
47 <DllImport("Kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ 48 Public Shared Function CreateFileTransacted( _ 49 <MarshalAs(UnmanagedType.LPWStr)> ByVal fileName As String, _ 50 ByVal fileAccess As Integer, _ 51 ByVal fileShare As Integer, _ 52 ByVal securityAttributes As IntPtr, _ 53 ByVal creationDisposition As Integer, _ 54 ByVal flags As Integer, _ 55 ByVal Template As IntPtr, _ 56 ByVal transaction As IntPtr, _ 57 ByVal miniVersion As IntPtr, _ 58 ByVal extendedOpenInformation As IntPtr) As Microsoft.Win32.SafeHandles.SafeFileHandle 59
60 End Function 61 #End Region
Observem a declaração das APIs para abertura e fechamento da transação e para a manipulação de arquivos, sendo que para a manipulação de arquivos existem inúmeras outras API's, esta classe está apenas fazendo um exemplo com a CreateFileTransacted e DeleteFileTransacted.
Elementos de Instância
7 Dim vIsTransacao As Boolean 8 Dim tx As IntPtr
99 #Region "Elementos de instância" 100
101 #Region "Controle transacional na classe" 102 Public Property IsTransacao() As Boolean 103 Get 104 Return vIsTransacao 105 End Get 106 Private Set(ByVal value As Boolean) 107 vIsTransacao = value
108 End Set 109 End Property 110
111 Public Sub AbrirTransacao() 112 tx = CreateTransaction(IntPtr.Zero, IntPtr.Zero, 0, 0, 0, Nothing, Nothing) 113 IsTransacao = True 114 End Sub 115
116 Public Sub Commit() 117 If IsTransacao Then 118 CommitTransaction(tx)
119 Else 120 Throw New ApplicationException("Não existe transacao") 121 End If 122 CloseHandle(tx)
123 IsTransacao = False 124 End Sub 125
126 Public Sub Rollback() 127 If IsTransacao Then 128 RollbackTransaction(tx)
129 Else 130 Throw New ApplicationException("Não existe transacao") 131 End If 132 CloseHandle(tx)
133 IsTransacao = False 134 End Sub 135
136 #End Region 137
138
139 #Region "Controle de arquivos na classe" 140 Public Sub DeletarArquivo(ByVal NomeArquivo As String) 141 DeleteFileTransacted(NomeArquivo, tx)
142 End Sub 143
144 Public Function CriarArquivo(ByVal nomearquivo As String) _ As Microsoft.Win32.SafeHandles.SafeFileHandle 145 If Not IsTransacao Then 146 Throw New _ ApplicationException("Este método foi criado para ser usado em uma transacao") 147 End If 148 Dim fh As Microsoft.Win32.SafeHandles.SafeFileHandle = _ 149 CreateFileTransacted(nomearquivo, _
150 GENERIC_READ Or GENERIC_WRITE, _ 151 0, _
152 IntPtr.Zero, _
153 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, _
154 IntPtr.Zero, tx, IntPtr.Zero, IntPtr.Zero)
155
156 Return (fh) 157 End Function 158 #End Region 159 #End Region
Os elementos de instância permitem o uso do KTM diretamente, planejados para serem utilizados junto com a clausula using, conforme exemplo anterior. Observe como o handle da transação é mantido como um atributo da instância, exigindo então a implementação do Dispose e padrão de finalização, que você vê a seguir :
162 #Region "Suporte de finalização" 163 Private disposedValue As Boolean = False ' To detect redundant calls 164
165 ' IDisposable 166 Protected Overridable Sub Dispose(ByVal disposing As Boolean) 167 If Not Me.disposedValue Then 168 If disposing Then 169 If IsTransacao Then 170 Rollback()
171 End If 172 End If 173 End If 174 Me.disposedValue = True 175 End Sub 176
177 #Region " IDisposable Support " 178 ' This code added by Visual Basic to correctly implement the disposable pattern. 179 Public Sub Dispose() Implements IDisposable.Dispose 180 ' Do not change this code. Put cleanup code in 'Dispose(ByVal disposing As Boolean) above. 181 Dispose(True) 182 GC.SuppressFinalize(Me) 183 End Sub 184 #End Region 185
186 Protected Overrides Sub finalize() 187 If IsTransacao Then 188 Rollback()
189 End If 190 End Sub 191 #End Region
Elementos Shared
63 #Region "Manipulacao com DTC" 64 Public Shared Sub DeletarArquivoDTC(ByVal NomeArquivo As String) 65 If IsNothing(Transaction.Current) Then 66 Throw New ApplicationException("Não existe transacao") 67 End If 68 Dim kt As IKernelTransaction 69 Dim handle As IntPtr 70 kt = TransactionInterop.GetDtcTransaction(Transaction.Current)
71 kt.GetHandle(handle)
72 DeleteFileTransacted(NomeArquivo, handle)
73 End Sub 74
75 Public Shared Function CriarArquivoDTC(ByVal NomeArquivo As String) _ As Microsoft.Win32.SafeHandles.SafeFileHandle 76 If IsNothing(Transaction.Current) Then 77 Throw New ApplicationException("Não existe transacao") 78 End If 79 Dim kt As IKernelTransaction 80 Dim handle As IntPtr 81 kt = TransactionInterop.GetDtcTransaction(Transaction.Current)
82 kt.GetHandle(handle)
83
84 Dim fh As Microsoft.Win32.SafeHandles.SafeFileHandle = _ 85 CreateFileTransacted(NomeArquivo, _
86 GENERIC_READ Or GENERIC_WRITE, _ 87 0, _
88 IntPtr.Zero, _
89 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, _
90 IntPtr.Zero, handle, IntPtr.Zero, IntPtr.Zero)
91
92 Return (fh) 93 End Function
Os elementos shared transferem a responsabilidade do controle transacional para o DTC, neste caso fazendo uso do System.Transactions confrome exemplo anterior. Observe como ambas as funções verificam a existência de uma transação atual e a utilizam para realizar a operação transacional. Para isso é utilizada uma interface chamada IKernelTransaction, que você vê a seguir :
196 <ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), _
197 Guid("79427A2B-F895-40e0-BE79-B57DC82ED231")> _ 198 Friend Interface IKernelTransaction 199 Sub GetHandle(ByRef handle As IntPtr)
Conclusão
|
|
|
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Quer
saber mais?
Faça um curso na Búfalo Informática, Treinamento e Consultoria e Prepare-se para o Mercado! Veja o que a Búfalo tem para você. |
© Búfalo Informática,
Treinamento e Consultoria -
Rua Álvaro Alvim, 37 Sala 920 • Cinelândia • Rio de Janeiro • RJ
Tel.: (21)2262-1368 • e-Mail: contato@bufaloinfo.com.br