23 04 2015
Dica rápida: Compactar mdb (Microsoft Access) programaticamente com C#
Não é segredo para ninguém que os arquivos mdb (do Microsoft Access) são facilmente corrompidos e que, uma vez que o tamanho deles cresce, ele não é automaticamente reduzido de tamanho. Se você abrir o arquivo mdb diretamente no Microsoft Access, é possível compactá-lo e repará-lo utilizando a opção “Compact and Repair Database“. Mas, como podemos fazer isso programaticamente utilizando C#? É isso que veremos na dica rápida de hoje.
Uma das opções para chamarmos a funcionalidade de compactação e reparação dos arquivos mdb é utilizarmos “Office Automation“. Porém, eu não recomendo essa prática, uma vez que é necessário que o Microsoft Office esteja instalado no computador cliente para que essa metodologia funcione. Portanto, não vou mostrá-la nesse artigo.
Ao invés disso, vou mostrar como compactar mdb utilizando a JetEngine. Para isso, o primeiro passo que temos que realizar no nosso projeto é adicionar uma referência à biblioteca COM chamada “Microsoft Jet and Replication Objects“:
Feito isso, adicione o seguinte método ao seu projeto:
public static void CompactarMdb(string caminhoMdb) { try { JRO.JetEngine jetEngine = (JRO.JetEngine)Activator.CreateInstance(Type.GetTypeFromProgID("JRO.JetEngine")); var arquivoTemporario = System.IO.Path.GetTempFileName(); arquivoTemporario = System.IO.Path.ChangeExtension(arquivoTemporario, "mdb"); string templateConnectionString = "Data Source={0};Provider=Microsoft.Jet.OLEDB.4.0;"; string connectionStringFonte = string.Format(templateConnectionString, caminhoMdb); string connectionStringTemp = string.Format(templateConnectionString, arquivoTemporario); jetEngine.CompactDatabase(connectionStringFonte, connectionStringTemp); System.IO.File.Copy(arquivoTemporario, caminhoMdb, true); System.IO.File.Delete(arquivoTemporario); } catch { } }
Note que o método para compactar o mdb é muito simples. Primeiramente criamos uma instância de JetEngine. Depois criamos um arquivo temporário com extensão mdb (o mdb compactado e reparado será armazenado nesse caminho). Então chamamos o método “CompactDatabase” passando a string de conexão apontando para o mdb original e a string de conexão apontando para o arquivo temporário. Finalmente, substituímos o arquivo original pelo arquivo temporário (que nesse ponto já deverá ser o mdb compactado e reparado).
A utilização desse método é muito fácil. Basta chamá-lo passando o caminho para o arquivo mdb:
CompactarMdb("C:\\Diretorio\\NomeDoMdb.mdb");
Viu como é simples compactar e reparar um mdb programaticamente utilizando C#? Espero que ajude outras pessoas que precisem resolver esse mesmo problema no futuro.
Até a próxima!
André Lima
Dica rápida: Filtrando os testes que serão executados na Integração Contínua do TFS Explorando o controle de mapas em aplicativos para a Windows Store
Show de bola.
Uma pena que meu arquivo esta com vários gigas de tamanho, causando um certo atraso durante o runtime do C#.
Abs
Olá Gustavo, obrigado pelo comentário!
Só uma dúvida: um banco do Microsoft Access com vários gigas? A chance de dar problemas é muito grande, hein.. A aplicação é acessada ao mesmo tempo por vários usuários ou somente um usuário o tempo todo? Os bancos do Access corrompem muito facilmente, principalmente quando começam a ficar muito grandes..
Nesse caso eu recomendaria que você analisasse uma possível migração para o SQL Server Express.. Você já pensou nisso?
Abraço!
André Lima
Ola André Lima
teria como vc postar o fonte já pronto
Olá Elielson!
Segue o link para download do projeto:
http://www.andrealveslima.com.br/files/artigos/compactarmdb/CompactarMdb.zip
Abraço!
André Lima
Muitíssimo obrigado André, sou usuário do delphi iniciando C# agora.
no momento sei apenas abrir o Visual Studio, rsrs.
Abraços.
Magina Elielson! Qualquer dúvida sobre esse ou outros assuntos relacionados, é só entrar em contato novamente.. Desejo muito sucesso aí nos seus projetos!
Abraço!
André Lima
Bom dia André, vou aproveitar suas palavras para tirar mais uma duvida,rsrs
Usei o fonte que postou e tentei adicionar um form e um textbox, o endereço do banco seria obtido através da textbox, e um butonn daria o comando para compactar, infelizmente não consigui realizar essa proeza, adepto do Delphi, to tendo dificuldades com visual.
Poderia me auxiliar nisso?
Aguardo retorno.
Olá Elielson!
Veja se te ajuda:
https://youtu.be/zj5GKTB0Uuo
Abraço!
André Lima
Oi vou colaborar um pouco, esse código aqui deu certo comigo para accdb
private void ribbonButton1_Click(object sender, EventArgs e)
{
DialogResult resultado = MessageBox.Show(“Para compactar a base de dados tenha certeza de que nenhuma usuário esteja utilizando o sistema!” + Environment.NewLine + Environment.NewLine + “Confirma a compactação da base de dados”, “Confirmação”, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (resultado == DialogResult.No)
{
return;
}
else
{
string retorno = CompactRepair();
if (retorno != “Ok”)
{
MessageBox.Show(retorno, “Bloqueio”, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
MessageBox.Show(“Base de Dados compactada com sucesso”, “Infomação”, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
public string CompactRepair()
{
var dbe = new Microsoft.Office.Interop.Access.Dao.DBEngine();
var arquivoTemporario1 = System.IO.Path.GetTempFileName();
var arquivoTemporario2 = System.IO.Path.GetTempFileName();
arquivoTemporario1 = Path.ChangeExtension(arquivoTemporario1, “accdb”);
arquivoTemporario2 = Path.ChangeExtension(arquivoTemporario2, “accdb”);
System.IO.File.Copy(Global.caminhoBD, arquivoTemporario1, true);
try
{
dbe.CompactDatabase(arquivoTemporario1, arquivoTemporario2);
System.IO.File.Copy(arquivoTemporario2, Global.caminhoBD, true);
System.IO.File.Delete(arquivoTemporario1);
System.IO.File.Delete(arquivoTemporario2);
return “Ok”;
}
catch (Exception e)
{
return e.Message;
}
}
Olá Sames!
Muito obrigado por compartilhar o código aqui! Não sabia que a dll de interop do Access implementava esse esquema de compactar e restaurar com suporte a arquivos accdb também.. Valeu!
Abraço!
André Lima
Na verdade, o código que eu postei é diferente do seu, porque ele usa o dbengine do DAO. O seu usa o JRO.Eu peguei a forma como você fez e a forma que um outro cara fez, juntei as duas e saiu esse que funciona para accdb.
Sames
Olá Sames!
Sim, eu vi que o seu código é diferente do meu.. Eu uso uma biblioteca e você usa outra.. Como eu disse no meu comentário anterior, eu não sabia que a dll de Interop do Access (que é a que você está utilizando: Microsoft.Office.Interop.Access.Dao.DBEngine) tinha essa funcionalidade para bancos accdb..
Abraço!
André Lima