locked
Problema acesso System.Assembly RRS feed

  • Pergunta

  • Boa Tarde pessoal,

    Estou com um problema de acesso.

    Preciso obter o caminho da aplicação para informar o caminho correto do banco de dados sdf.

    Código:

     Dim Programa As System.Reflection.Assembly
     Dim strCaminho As String
    
     Programa = System.Reflection.Assembly.GetExecutingAssembly
    
     strCaminho = Programa.GetModules(0).FullyQualifiedName
    
     strCaminho = System.IO.Path.GetDirectoryName(strCaminho) & "\"
    
     

    Quando a execução chega na linha "strCaminho = Programa.GetModules(0).FullyQualifiedName" recebo o erro:

    Attempt to access the method failed: System.Reflection.Module.get_FullyQualifiedName()

    Se isso não funcionar, como posso obter o caminho correto do banco de dados?

    Obrigado 


    Analista Programador .Net www.fabner.com.br

    segunda-feira, 30 de abril de 2012 16:58

Respostas

  • Fabner, falta-te a verificação se a base de dados não existir, então deve ser criada, usando os métodos DatabaseExists() e CreateDatabase() do datacontext respectivamente.

    Pedro Lamas
    DevScope | Senior Software Development Engineer & WP7 Development Speaker
    www.pedrolamas.com | @pedrolamas

    • Marcado como Resposta FPimenta domingo, 6 de maio de 2012 15:12
    terça-feira, 1 de maio de 2012 18:03
  • Fabner,

    A primeira pergunta para saber qual a resposta correta é: essa sua base de dados será somente leitura, ou terá gravação nela?

    Se for somente leitura, vc consegue acessar direto de uma pasta do seu projeto, mas a string de conexão não será a que está utilizando.

    Agora, se for leitura e gravação, vc terá que copiar a base para o isolatedstorage, para despois acessá-la. Faço isso em alguns projetos e funciona perfeito.
    Para copiar o arquivo e depois acessar, tente o seguinte:

    public void Teste()
    {
    
        using (WPDataContext db = new WPDataContext(WPDataContext.DBConnectionString))
        {
            if (db.DatabaseExists() == false)
            {
                //Se quiser criar um banco vazio :)
                //db.CreateDatabase();
                this.CopyDatabase();
            }
        }
    }
    
    private void CopyDatabase()
    {
        using (Stream db = Application.GetResourceStream(new Uri("DBTeste.sdf", UriKind.Relative)).Stream)
        {
            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream workDB = isoStore.CreateFile("DBTeste.sdf"))
                {
                    using (BinaryWriter writer = new BinaryWriter(workDB))
                    {
                        long length = db.Length;
                        byte[] buffer = new byte[32];
                        int readCount = 0;
                        using (BinaryReader reader = new BinaryReader(db))
                        {
                            // read file in chunks in order to reduce memory consumption and increase performance                                                                
                            while (readCount < length)
                            {
                                int actual = reader.Read(buffer, 0, buffer.Length);
                                readCount += actual;
                                writer.Write(buffer, 0, actual);
                            }
                        }
                    }
                }
            }
        }
    }

    Lembrando que o WPDataContext que está no exemplo, deve ser substituído pela sua classe de contexto.

    []s


    Thiago J. Mônaco
    MVP Windows Phone Development
    MCP, MCAD, MCSD, MCDBA, MCTS, MCPD and MCT Professional
    Scrum Developer I and Professional Scrum Master
    http://www.windowsphonebrasil.net
    @thiagojmonaco

    • Marcado como Resposta FPimenta domingo, 6 de maio de 2012 15:11
    quarta-feira, 2 de maio de 2012 14:10
  • Fabner,

    A única coisa que acabei de perceber é que na sua string de conexão, falta um :

    Public Const SQLConn As String = "Data Source=isostore:/DBTeste.sdf"

    Veja o que acontece fazendo essa correção, pq de resto aparentemente está tudo certo.
    Se não funcionar, me avise pois damos um jeito de resolver :)

    []s


    Thiago J. Mônaco
    MVP Windows Phone Development
    MCP, MCAD, MCSD, MCDBA, MCTS, MCPD and MCT Professional
    Scrum Developer I and Professional Scrum Master
    http://www.windowsphonebrasil.net
    @thiagojmonaco

    • Marcado como Resposta FPimenta domingo, 6 de maio de 2012 15:11
    sexta-feira, 4 de maio de 2012 12:00

Todas as Respostas

  • Fabner, não precisas de fazer isso para a base de dados!

    Aliás, todo o storage de uma app do Windows Phone é isolada (IsolatedStorage) e como tal, é relativa a esse mesmo storage (daí que nunca precisamos de saber o caminho da aplicação em si!)

    A connection string deve ser algo tipo "Data Source=isostore:/A_minha_base_de_dados.sdf", bastando assim substituíres o nome da base de dados.

    aqui como deves fazer para indicar o caminho para a base de dados!


    Pedro Lamas
    DevScope | Senior Software Development Engineer & WP7 Development Speaker
    www.pedrolamas.com | @pedrolamas

    segunda-feira, 30 de abril de 2012 17:42

  • Olá pedro.

    Foi exatamente por ocorrer o problema com caminho da base de dados que tentei obter o caminho pelo assembly.

    Minha string de conexao está exatamente igual a sua e mesmo assim gera o erro:

    "The database file cannot be found. Check the path to the database. [ Data Source = \Applications\Data\7556F360-987A-4686-BEAB-76751ECA1E48\Data\IsolatedStore\DBTeste.sdf ]"

    OBS: Estou programando em vb.net


    Analista Programador .Net www.fabner.com.br

    segunda-feira, 30 de abril de 2012 18:08
  • Fabner,

    Se puder colocar o trecho do código que está utilizando, podemos dar uma olhada.

    []s


    Thiago J. Mônaco
    MVP Windows Phone Development
    MCP, MCAD, MCSD, MCDBA, MCTS, MCPD and MCT Professional
    Scrum Developer I and Professional Scrum Master
    http://www.windowsphonebrasil.net
    @thiagojmonaco

    terça-feira, 1 de maio de 2012 15:36
  • Thiago,

    Primeiro, gerei as classes responsáveis pela conexão de dados via SQLMETAL.

    As classes estão no mesmo projeto. Depois comecei a criar um código para testar

    Partial Public Class Consulta
        Inherits PhoneApplicationPage
    
        Public Const SQLConn As String = "Data Source=isostore:/DBTeste.sdf"
    
        Public Sub New()
            InitializeComponent()
    
            CarregaListaConsulta()
    
        End Sub
    
    
        Private Function ObterCaminho() As String
    
            Dim Programa As System.Reflection.Assembly
            Dim strCaminho As String
    
            Programa = System.Reflection.Assembly.GetExecutingAssembly
    
            strCaminho = Programa.GetModules(0).FullyQualifiedName
    
            strCaminho = System.IO.Path.GetDirectoryName(strCaminho) & "\"
    
            Return strCaminho
    
        End Function
    
    
    
        Private Sub CarregaListaConsulta()
    
            Dim objDA As clsAcessoDadosT = New clsAcessoDadosT(SQLConn)
    
            Dim qConsulta As IQueryable(Of Tb_Consulta) = Nothing
    
            qConsulta = objDA.Tb_Consulta
    
            Dim qConsulta2 As IQueryable(Of TbConsulta2)
    
            qConsulta2 = objDA.TbConsulta2
    
            Dim qResultados = From oConsulta In qconsulta
                            Join oConsulta2 In qConsulta2
                            On oConsulta.Id Equals oConsulta2.Id
                            Select
                            oconsulta.Id,
                            oConsulta.Titulo
                            
            Dim ListaItemsView As New List(Of clsListaItemsView)
    
            For i As Integer = 0 To qResultados.Count - 1
    
                Dim oListaItemView As New clsListaItemsView
    
                With oListaItemView
                    .Id = qResultados(i).Id
                    .Titulo = qResultados(i).Titulo
                End With
    
                ListaItemsView.Add(oListaItemView)
    
            Next
    
            lstItens.ItemsSource = ListaItemsView
    
        End Sub
    
    End Class
    

    Pode ver que o código é coisa simples, criei um sdf com duas tabelas com duas colunas cada, depois usei LINQ só para fazer o relacionamento e jogar em uma lista.

    Abraço


    Analista Programador .Net www.fabner.com.br

    terça-feira, 1 de maio de 2012 17:57
  • Fabner, falta-te a verificação se a base de dados não existir, então deve ser criada, usando os métodos DatabaseExists() e CreateDatabase() do datacontext respectivamente.

    Pedro Lamas
    DevScope | Senior Software Development Engineer & WP7 Development Speaker
    www.pedrolamas.com | @pedrolamas

    • Marcado como Resposta FPimenta domingo, 6 de maio de 2012 15:12
    terça-feira, 1 de maio de 2012 18:03
  • Pedro,

    Minha base existe em arquivo. ela está na mesma pasta do projeto.

    No momento de rodar no Emulador o VS2010 tem que jogar o arquivo lá.

    Pelo meno é o que eu entendi até agora.

    Quando você cria uma base sdf e usa o sqlmetal, é necessário ainda criála em tempo de execução?


    Analista Programador .Net www.fabner.com.br

    terça-feira, 1 de maio de 2012 18:11
  • Não, se ela já existe está tudo ok, mas há uma alteração a fazer: em vez de "Data Source=isostore:/DBTeste.sdf" usas "Data Source=appdata:/DBTeste.sdf" pois a base de dados está na pasta da aplicação e não no IsolatedStorage!

    Nota que tens de ter o ficheiro *.sdf no projecto e nas propriedades dele tem de ter o "Build Action" em "Content" para que ele copie a base de dados junto com a aplicação, e nota também que dado que ela vai estar no appdata, é só de read-only!

    No artigo que te indiquei no meu primeiro post, isto é referido, e até a parte de como enviar uma base de dados pronta junto com a aplicação, copiar a mesma para o IsolatedStorage para que possa ser alterada, se assim for preciso!


    Pedro Lamas
    DevScope | Senior Software Development Engineer & WP7 Development Speaker
    www.pedrolamas.com | @pedrolamas

    terça-feira, 1 de maio de 2012 18:15
  • Pedro,

    Testei mas não deu certo.

    Alterei isostore para appdata e o erro continua o mesmo.

    Este erro está ocorrendo quando utilizo o ".Count" conforme codigo postado acima.


    Analista Programador .Net www.fabner.com.br

    terça-feira, 1 de maio de 2012 18:41
  • E o ficheiro da base de dados (*.sdf) está referenciado na raiz do projecto, e o seu "Build Action" em "Content"?

    Faz também um Rebuild da aplicação e depois novo Deploy antes de experimentar novamente!


    Pedro Lamas
    DevScope | Senior Software Development Engineer & WP7 Development Speaker
    www.pedrolamas.com | @pedrolamas

    terça-feira, 1 de maio de 2012 18:44
  • Mesmo assim o erro continua.

    Fiz Rebuild e o BuildAction está como Content.


    Analista Programador .Net www.fabner.com.br

    terça-feira, 1 de maio de 2012 18:55
  • Fabner,

    A primeira pergunta para saber qual a resposta correta é: essa sua base de dados será somente leitura, ou terá gravação nela?

    Se for somente leitura, vc consegue acessar direto de uma pasta do seu projeto, mas a string de conexão não será a que está utilizando.

    Agora, se for leitura e gravação, vc terá que copiar a base para o isolatedstorage, para despois acessá-la. Faço isso em alguns projetos e funciona perfeito.
    Para copiar o arquivo e depois acessar, tente o seguinte:

    public void Teste()
    {
    
        using (WPDataContext db = new WPDataContext(WPDataContext.DBConnectionString))
        {
            if (db.DatabaseExists() == false)
            {
                //Se quiser criar um banco vazio :)
                //db.CreateDatabase();
                this.CopyDatabase();
            }
        }
    }
    
    private void CopyDatabase()
    {
        using (Stream db = Application.GetResourceStream(new Uri("DBTeste.sdf", UriKind.Relative)).Stream)
        {
            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream workDB = isoStore.CreateFile("DBTeste.sdf"))
                {
                    using (BinaryWriter writer = new BinaryWriter(workDB))
                    {
                        long length = db.Length;
                        byte[] buffer = new byte[32];
                        int readCount = 0;
                        using (BinaryReader reader = new BinaryReader(db))
                        {
                            // read file in chunks in order to reduce memory consumption and increase performance                                                                
                            while (readCount < length)
                            {
                                int actual = reader.Read(buffer, 0, buffer.Length);
                                readCount += actual;
                                writer.Write(buffer, 0, actual);
                            }
                        }
                    }
                }
            }
        }
    }

    Lembrando que o WPDataContext que está no exemplo, deve ser substituído pela sua classe de contexto.

    []s


    Thiago J. Mônaco
    MVP Windows Phone Development
    MCP, MCAD, MCSD, MCDBA, MCTS, MCPD and MCT Professional
    Scrum Developer I and Professional Scrum Master
    http://www.windowsphonebrasil.net
    @thiagojmonaco

    • Marcado como Resposta FPimenta domingo, 6 de maio de 2012 15:11
    quarta-feira, 2 de maio de 2012 14:10
  • Olá Thiago,

    Respondendo a sua pergunta, sim, preciso armazenar, atualizar e deletar registros na base de dados.

    Criei os metodos sugeridos em vb:

    Public Class clsManutencao
    
        Public Sub VerificarBancoDeDados(ByVal StringConexao As String)
    
            Dim oContext As New clsAcessoDadosT(StringConexao)
    
            If Not oContext.DatabaseExists Then
    
                CopiarBancoDeDados()
    
            End If
    
        End Sub
    
    
        Private Sub CopiarBancoDeDados()
    
            Dim db As Stream = Application.GetResourceStream(New Uri("DBTeste.sdf", UriKind.Relative)).Stream
    
            Dim isoStore As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()
    
            Dim workDB As IsolatedStorageFileStream = isoStore.CreateFile("DBTeste.sdf")
    
            Dim bWriter As BinaryWriter = New BinaryWriter(workDB)
    
            Dim Tamanho As Long = db.Length
            Dim Buffer(32) As Byte
            Dim intCont As Integer
    
            Dim bReader As BinaryReader = New BinaryReader(db)
    
            While intCont < Tamanho
    
                Dim intAtual = bReader.Read(Buffer, 0, Buffer.Length)
    
                intCont += intAtual
    
                bWriter.Write(Buffer, 0, intAtual)
    
            End While
    
        End Sub
    
    End Class

    Depois, no código da MainPage

    Partial Public Class MainPage
        Inherits PhoneApplicationPage
    
        Public Const SQLConn As String = "Data Source=isostore/DBTeste.sdf"
    
    
        ' Constructor
        Public Sub New()
    
            InitializeComponent()
    
            Dim oManutencao As New clsManutencao
    
            oManutencao.VerificarBancoDeDados(SQLConn)
    
        End Sub
    
    
    End Class

    Até aqui sem problemas, o metodo é chamado  mas quando executo o codigo já postado anteriormente, recebo o erro

    Access to the database file is not allowed. [ 1981,File name = \Applications\Install\7556F360-987A-4686-BEAB-76751ECA1E48\Install\DBTeste.sdf,SeCreateFile ]

    Tentei criar  a base direto pela classe de contexto mas mesmo assim não funcionou:

    Partial Public Class MainPage
        Inherits PhoneApplicationPage
    
        Public Const SQLConn As String = "Data Source=isostore/DBTeste.sdf"
    
    
        ' Constructor
        Public Sub New()
    
            InitializeComponent()
    
            Dim oContexto As New clsAcessoDadosT(SQLConn)
    
            If Not oContexto.DatabaseExists Then
                oContexto.CreateDatabase()
            Else
                Stop
            End If
    
        End Sub

    Quando o metodo CreateDatabase é executado ocorre o seguinte erro:

    Cannot create or delete database outside of application isolated storage.

    Abraço


    Analista Programador .Net www.fabner.com.br

    sexta-feira, 4 de maio de 2012 00:51
  • Fabner,

    A única coisa que acabei de perceber é que na sua string de conexão, falta um :

    Public Const SQLConn As String = "Data Source=isostore:/DBTeste.sdf"

    Veja o que acontece fazendo essa correção, pq de resto aparentemente está tudo certo.
    Se não funcionar, me avise pois damos um jeito de resolver :)

    []s


    Thiago J. Mônaco
    MVP Windows Phone Development
    MCP, MCAD, MCSD, MCDBA, MCTS, MCPD and MCT Professional
    Scrum Developer I and Professional Scrum Master
    http://www.windowsphonebrasil.net
    @thiagojmonaco

    • Marcado como Resposta FPimenta domingo, 6 de maio de 2012 15:11
    sexta-feira, 4 de maio de 2012 12:00
  • Fabner,

    A única coisa que acabei de perceber é que na sua string de conexão, falta um :

    Public Const SQLConn As String = "Data Source=isostore:/DBTeste.sdf"

    Veja o que acontece fazendo essa correção, pq de resto aparentemente está tudo certo.
    Se não funcionar, me avise pois damos um jeito de resolver :)

    []s


    Thiago J. Mônaco
    MVP Windows Phone Development
    MCP, MCAD, MCSD, MCDBA, MCTS, MCPD and MCT Professional
    Scrum Developer I and Professional Scrum Master
    http://www.windowsphonebrasil.net
    @thiagojmonaco

    Obrigado Thiago, era isso mesmo.

    Resumindo, o VS2010 não copia a base automaticamente para o isostore (eu pensava que copiava).

    A conexao ficou como "Data Source=isostore:/DBTeste.sdf"

    Estava faltando o ":".

    Utilizei o método de criação de base e agora não apresenta mais erro.

    Agora vou fazer testes com inserção de dados.

    Abraço


    Analista Programador .Net www.fabner.com.br

    domingo, 6 de maio de 2012 15:11