none
Datatable disponível em todo o aplicativo RRS feed

  • Pergunta

  • Tenho uma tabela de clientes (SQL Server) com uns 20 mil registros. Como eu vou ter no meu aplicativo vários combobox e datagrid em que preciso dos nomes e ID dos clientes, pensei em carregar um datatable logo no início do programa e deixa-lo disponível para acesso quando precisar.

    O objetivo é não precisar ficar executando a consulta a toda hora, pois é demorado. Perguntas:

    Esta é a melhor maneira? Como fazer para que o datatable fique com um escopo "global"?

    domingo, 30 de outubro de 2016 23:03

Respostas

  • Olá Paulo,

    Você pode fazer de duas maneiras que me veem a cabeça agora.

    Carregar o dataset no form principal e pode passar esse dataset sempre quando inicializar/abrir um novo form, através de um construtor personalizado. Por exemplo:

    //Form principal
    DataTable dt = new DataTable(); 
    ... //carrega os dados, etc
    
    //chamando o form 2 e passando o datatable já carregado
    Form2 f2 = new Form2(dt);
    
    
    // Classe do form 2
    public partial class Form2 : Form
    {
       private DataTable dt;
       Public Form2(DataTable dt)
       {
           this.dt = dt;
       }
    }

    A outra maneira é criar uma classe intermediária entre a Classe Form e os seus Forms, por exemplo:

    public class MinhaClasse : Form
    {
        public DataTable dt = new DataTable
        //Carrega todos os dados
    }
    
    // Terás que editar os forms para herdar da sua classe e não diretamente da classe Form do C#, dessa forma terão acesso ao DataTable
    
    public partial class Form1 : MinhaClasse 
    {
       DataTable = base.dt;
    }

    Esse é apenas um exemplo, mas dá pra ter noção de como você pode fazer.

    Espero ter ajudado.

    Valeu!


    Se a resposta for relevante ou tenha resolvido seu problema, marque como útil/resposta!

    André Secco
    Microsoft MSP & MSDN Tech Advisor
    Blog: http://andresecco.com.br
    GitHub: http://github.com/andreluizsecco
    Twitter: @andre_secco

    • Marcado como Resposta Paulo 15 terça-feira, 1 de novembro de 2016 01:18
    segunda-feira, 31 de outubro de 2016 10:00

Todas as Respostas

  • Olá Paulo,

    Você pode fazer de duas maneiras que me veem a cabeça agora.

    Carregar o dataset no form principal e pode passar esse dataset sempre quando inicializar/abrir um novo form, através de um construtor personalizado. Por exemplo:

    //Form principal
    DataTable dt = new DataTable(); 
    ... //carrega os dados, etc
    
    //chamando o form 2 e passando o datatable já carregado
    Form2 f2 = new Form2(dt);
    
    
    // Classe do form 2
    public partial class Form2 : Form
    {
       private DataTable dt;
       Public Form2(DataTable dt)
       {
           this.dt = dt;
       }
    }

    A outra maneira é criar uma classe intermediária entre a Classe Form e os seus Forms, por exemplo:

    public class MinhaClasse : Form
    {
        public DataTable dt = new DataTable
        //Carrega todos os dados
    }
    
    // Terás que editar os forms para herdar da sua classe e não diretamente da classe Form do C#, dessa forma terão acesso ao DataTable
    
    public partial class Form1 : MinhaClasse 
    {
       DataTable = base.dt;
    }

    Esse é apenas um exemplo, mas dá pra ter noção de como você pode fazer.

    Espero ter ajudado.

    Valeu!


    Se a resposta for relevante ou tenha resolvido seu problema, marque como útil/resposta!

    André Secco
    Microsoft MSP & MSDN Tech Advisor
    Blog: http://andresecco.com.br
    GitHub: http://github.com/andreluizsecco
    Twitter: @andre_secco

    • Marcado como Resposta Paulo 15 terça-feira, 1 de novembro de 2016 01:18
    segunda-feira, 31 de outubro de 2016 10:00
  • A resposta do André é boa, mas entendi diferente a pergunta do Paulo.
    Pelo que eu entendi ele quer deixar em um local "neutro" onde as demais classes possam acessar; se ele deixar no Form principal e passar como argumento para os filhos resolveria o problema, mas ele teria que fazer isso em todos os filhos.

    Pegando o complemento da pergunta, como colocar no "global", a resposta é mais simples do que parece Paulo. O "global" é o namespace raiz do assembly. De todos os assemblies carregados.

    Então, note que nos arquivos CS suas classes são assim:

    namespace abc.cde
    {
        public class fgh { }
    }

    Então você está no namespace "abc", que tem um namespace "cde" e que tem a classe "fgh"; podendo chamar por "global::abc.cde.fgh". Pois bem, se você ficar isso:

    public class Source
    {
        public static DataTable clientes;
    }

    Diretamente no arquivo CS não haverá namespace, logo a classe será chamada por "global::Source" e colocando a variável clientes como static, qualquer classe do programa poderá acessá-la, sem instancias a classe. Você pode ainda fazer um construtor estático para a classe, abastecendo a tabela clientes logo ao carregar o programa (na verdade ao criar a classe na memória, mas enfim).

    public class Source
    {
        public static DataTable clientes;
    
        static Source()
        {
            //'... aqui, inicialize clientes
        }
    }
    • Sugerido como Resposta SammuelMiranda segunda-feira, 31 de outubro de 2016 10:30
    segunda-feira, 31 de outubro de 2016 10:30
  • Paulo, carregar 20 mil registros para um DataTable e deixar carregado durante toda execução da sua aplicação pode "resolver" um problema e criar outro, afinal sua aplicação utilizará uma quantidade elevada de memória RAM durante toda sua execução.

    Eu lhe sugiro duas alternativas mais apropriadas para este tipo de situação:

    1- Implementar o recurso de cache (seja com as classes do .Net ou com frameworks de terceiros), caso sejam poucas colunas que precise. O cache não vai obrigatoriamente ficar o tempo todo em memória e vai evitar as idas ao banco de dados;

    2- Se o número de colunas for grande, outra boa opção é utilizar o SQL Server LocalDB (https://msdn.microsoft.com/pt-br/library/hh510202.aspx?f=255&MSPPError=-2147217396), que como o próprio nome diz trata-se de uma base local que você pode carregar completamente no início de sua aplicação ou até mesmo trabalhar com sincronização dos dados (https://msdn.microsoft.com/en-us/library/mt490616.aspx).

    Mas se mesmo assim você quiser usar uma variável global, sugiro se basear no pattern Singleton para implementar o recurso, desta forma independente de qual seja o form de entrada, a primeira utilização irá carregar os dados e as posteriores vão apenas reutilizar o que já está em memória.

    public static class Dados
    {
        private static DataTable _dt;
    
        public static DataTable
        {
            get
            {
                if (_dt == null)
                {
                    CarregarDadosDoBanco();
                }
                return _dt;
            }
            set
            {
                _dt = value;
            }
        }
    }

    Fica a dica.


    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, remember to "Mark as Answer".

    Se achou este post útil, por favor clique em "Votar como útil". Se por acaso respondeu sua dúvida, lembre de "Marcar como Resposta".

    segunda-feira, 31 de outubro de 2016 10:34
  • Boa tarde Paulo

    Existem diversas maneiras

    jogar numa propriedade Static e depois trabalhar com lambda e assim poder adequar em qualquer datasource de suas combobox. 

    Setar uma Session e fazer uma conversão

    Session["ssnDt"] = DataTable Dt_1 = obj.Pesquisa(Parametos);

    DataTable Dt_2 = (DataTable)Session["ssnDt"]

    enfim... existem diversas maneiras. Espero ter ajudado.

    Att.

    segunda-feira, 31 de outubro de 2016 17:25