USANDO CONNECTION STRINGS

 Tópico anterior Próximo tópico Novo tópico

USANDO CONNECTION STRINGS

VB.NET

 Compartilhe  Compartilhe  Compartilhe
#499434 - 11/03/2022 23:32:58

NOWLIGHTS
SUMARE
Cadast. em:Abril/2011


Última edição em 11/03/2022 23:35:46 por NOWLIGHTS

Boa noite!

Ando usando a connection string em ASP.NET CORE MVC da seguinte forma, na camada de dados (dal), crio uma classe chamada conec() com o seguinte:

    public class conec
    {

        public MySqlConnection Get()
        {
            string ConnectionString = 'Server=SERVIDOR;Database=DATA_BASE;Uid=USER;Pwd=SENHA;';
            return new MySqlConnection(ConnectionString);
        }
    }


Para usar com o Dapper (using (MySqlConnection cn = new conec().Get()....))

Porém, já vi muitos casos onde indicam o uso do appsettings.json, só que, não estava conseguindo passar os valores em json da appsetings.json do projeto principal para a biblioteca de classes DAL, então cheguei no acordo, criar uma clase base onde busca o appsettings.json e armazena na string, exemplo:

  public class BaseDAL
    {
      
        private readonly string _connectionString = string.Empty;
        public BaseDAL()
        {
            var configurationBuilder = new ConfigurationBuilder();
            var path = Path.Combine(Directory.GetCurrentDirectory(), 'appsettings.json');
            configurationBuilder.AddJsonFile(path, false);
            var root = configurationBuilder.Build();
            _connectionString = root.GetSection('ConnectionStrings').GetSection('myconec').Value;
        }

        public string ConnectionString { get => _connectionString; }
    }


E na minha classe conec:

  public class conec : BaseDAL
    {

        public MySqlConnection Get()
        {
            return new MySqlConnection(ConnectionString); // herdando BaseDAL e pegando a propriedade ConnectionString
        }
    }



E quando precisar usar em algum lugar dentro da camada DAL:

  
public class Cliente
     public async Task<Cliente> GetCliente(){
          using(mysqlconnection cn = new conec().get()......
     }


Só que, desta maneira, cada conexão com o banco de dados, o sistema faria uma leitura deste appsettings.json... certo? com isso, aumentaria, pelo menos um pouco, a lentidão na operação de busca ao banco de dados...

Da maneira que mostrei no começo, armazenando a connection string em uma prorpeidade dentro da biblioteca de classes, é brecha de segurança?


__________________________________
- Everyone has a chance


#499435 - 12/03/2022 09:10:16

MARCELOKROL
REBOUCAS
Cadast. em:Julho/2004


Também é uma dúvida minha.

Vi em alguns exemplos usando assim:
- na classe Startup:
  
(...)
var connectionString = configuration.GetConnectionString('DefaultConnection');
Environment.SetEnvironmentVariable('conn', connectionString);
(...)


- depois quando precisar, requisita o conteúdo dela (por exemplo no OnConfiguring, do seu Context):
  
var conn = Environment.GetEnvironmentVariable('conn');


Fica a dica, mas seria interessante o retorno de alguém experto nesse quesito, de qual a melhor forma de se armazenar/requisitar.



#499437 - 12/03/2022 09:18:12

KERPLUNK
RIO GRANDE DO SUL
Cadast. em:Junho/2009


Membro da equipe
Se você armazena suas variáveis no JSON de configuração, não tem jeito, vai ter que ser lida. Essa mentalidade de 'em memória', não funciona muito com aplicações stateless. O mais parecido com isso seria o uso de ID(injeção de dependência).

_______________________________________________________________________
Virei Orculo!
The end is nigh, be ready for the nukes!


#499457 - 17/03/2022 01:40:58

DS2T
BARRA MANSA
Cadast. em:Novembro/2010


Vamos lá, vou tentar esclarecer alguns pontos.

Usando appsettings.json para armazenar string de conexão

Quando você está trabalhando em ambientes corporativos é comum que você possua mais de um ambiente da aplicação: desenvolvimento, homologação, produção, etc...   Na verdade, até mesmo quando você está trabalhando fora do ambiente corporativo, você geralmente roda a aplicação localmente, acessando um banco de dados para desenvolvimento e depois quando publica, ele acessa o banco de produção.

O appsettings é uma forma simples para você ter um arquivo de configuração para cada ambiente. Assim você não precisa mudar seu código (mudando a string de conexão) toda vez que vai fazer uma publicação.
E isso estamos falando só do banco de dados. Agora imagina que você acessa APIs na sua aplicação, acessa serviços de nuvem, etc. Imagina o tanto de mudança que você precisaria fazer no código. No fim, você provavelmente teria duas classes separadas com as configurações de cada ambiente e mudaria apenas num lugar. Mas isso ainda tem outros problemas, porque você vai estar expondo possíveis dados sensíveis (senha do banco de produção, dados de autenticação de serviço, etc). Então ter appsettings é uma boa.

Existem outras formas de fazer isso, mas o appsettings é o jeito convencional no .NET.


Só que, desta maneira, cada conexão com o banco de dados, o sistema faria uma leitura deste appsettings.json... certo?

O problema está na forma com que você está fazendo.
A sua classe DAO não deveria ter o papel de configurar e apontar para o appsettings. Por padrão o .NET trabalha com valores de configuração cacheados, isto é, ele vai ler os dados apenas uma vez e deixar em memória. Só que da forma que você tá fazendo, criando um builder toda vez, ele acaba acessando o arquivo toda hora. E acessar disco é custoso.

Essas configurações você vai fazer apenas no começo da aplicação e as configurações serão injetadas na sua classe BaseDao.
Olha um exemplo simples do Macoratti:

http://www.macoratti.net/20/11/aspnc_optsimpl1.htm

O .NET oferece várias implementações para o IOptions, você pode ir brincando com elas.


Sobre variáveis de ambiente...

É possível sim usar variáveis de ambiente, mas isso dificulta seus testes unitários. Trabalhar com uma configuração de banco como dependência no construtor é muito mais intuitivo também.

Seja como for, se bem usado, o esquema de configuration do .NET é extremamente eficiente por deixar os dados igualmente em memória após lidos uma vez. Existem implementações do IOptions que você também pode decidir quanto tempo o valor irá ficar cacheado (sendo esse caso para fazer valer alterações do appsettings sem você precisar reiniciar a aplicação - essa implementação a parte só reafirma que os valores são cacheados por padrão, por isso que depois que a aplicação inicia você pode modificar seu appsettings a vontade e não sofrerá com as alterações até a aplicação ser reiniciada)

Programo por amor... amor ao dinheiro para pagar as contas...


#499461 - 17/03/2022 13:25:39

NOWLIGHTS
SUMARE
Cadast. em:Abril/2011


Citação:
  Essas configurações você vai fazer apenas no começo da aplicação e as configurações serão injetadas na sua classe BaseDao.
Olha um exemplo simples do Macoratti:

http://www.macoratti.net/20/11/aspnc_optsimpl1.htm


Eu ainda não manjo muito de injeção de dependência, mas, no caso de adicionar essa injeção na BaseDAL, no construtor, ao precisar chamar o dRepository que herda de BaseDAL, eu preciso passar o objeto junto... mas qual objeto passar kkk

Acredito que esteja completamente errado esse modo, mas o que eu pouco entendi;

   public class BaseDAL
    {
      
        private readonly MyConfig _myConfig;
        public BaseDAL(MyConfig myconfig)
        {
            _myConfig = myconfig;
        }
        public string ConnectionString { get => _myConfig.myconec; }
    }


No startup;

    public void ConfigureServices(IServiceCollection services)
        {
            var myconfig = new MyConfig();
            Configuration.Bind('ConnectionStrings', myconfig);
            services.AddSingleton(myconfig);

            services.AddControllersWithViews();


        }


__________________________________
- Everyone has a chance


#499522 - 26/03/2022 16:52:18

DS2T
BARRA MANSA
Cadast. em:Novembro/2010


Opa, desculpa a demora.

Citação:
Eu ainda não manjo muito de injeção de dependência, mas, no caso de adicionar essa injeção na BaseDAL, no construtor, ao precisar chamar o dRepository que herda de BaseDAL, eu preciso passar o objeto junto... mas qual objeto passar kkk



Essa é a vantagem de usar um container de injeção de dependência, você não precisa instanciar as classes. O container vai resolver todas as dependências.
Então você colocaria até sua classe DAO no escopo da injeção de dependência.


Citação:
Acredito que esteja completamente errado esse modo, mas o que eu pouco entendi;


Não está completamente errado. Está bacana, o problema é que essa abordagem faz com que você precise colocar seu DAO também no container de injeção de dependência.
Recomendo que você pense com caminho em utilizar esse recurso, é interessante.

Mas se você tem uma aplicação já em uso e quer mudar somente essa parte da DAO sem se comprometer com um impacto muito grande. Use uma classe estática e carregue ela com os dados do app.settings no Startup. E use ela na sua DAO. O problema com isso é que vai ser difícil criar testes unitários depois. Mas por outro lado, testes unitários em DAO não costumam fazer muito sentido, então não seria uma violação tão incômoda assim.

Se você tiver só fazendo um exemplo, me passa seu código que eu posso alterar aqui pra você ver como ficaria com Dependency Injection.

Abraços!

Programo por amor... amor ao dinheiro para pagar as contas...


#499533 - 28/03/2022 20:29:25

NOWLIGHTS
SUMARE
Cadast. em:Abril/2011


Então, a arquitetura 'padrão' que eu sempre sigo, é esse modelo

Primeiro, tenho a camada de acesso a dados;

namespace Prop.DAL
{
    public class conec
    {
        public MySqlConnection Get()
        {
            string ConnectionString = 'QUERY_CONNECTION...';
            return new MySqlConnection(ConnectionString);
        }
    }

    public class dCliente
    {
        public async Task<Cliente> GetCliente(int IdCliente)
        {
            try
            {
                var param = new { IdCliente };
                var sql = $'SELECT FROM {Cliente.TableName} WHERE Id=@IdCliente';
                using (MySqlConnection cn = new conec().Get())
                {
                    var res = await cn.QueryAsync<Cliente>(sql, param);
                    return res.FirstOrDefault();
                }
            }
            catch (System.Exception) { throw; }
        }
    }
}


Depois camada de negócios


namespace Prop.BLL
{
    public class bslCliente
    {
        private readonly dCliente _CliR = new dCliente();
        public async Task<Cliente> GetCliente(IdCliente)
        {
            try { return await _CliR.GetCliente(IdCliente); } catch (System.Exception) { throw; }
        }
    }
}



E por último a UI...


namespace Prop.UI
{
    public class ClienteController : Controller
    {
        private readonly bslCliente _CliR = new bslCliente();

        [Route('/Cliente/{IdCliente}')]
        public async Task<IActionResult> ClienteGet(int IdCliente)
        {
            if(IdCliente == 0) return NotFound();
            var vm = new VM_CLiente();
            vm._Cliente = await _CliR.GetCliente(IdCliente);
            return View(vm);
        }
    }
}


padrão bem simples e objetivo, nada complexo. Más como mandaria a ConnectionString na AppSettings.Json por essas camadas

__________________________________
- Everyone has a chance


#499534 - 28/03/2022 21:44:40

KERPLUNK
RIO GRANDE DO SUL
Cadast. em:Junho/2009


Membro da equipe
Essas settings tem que ficar lá na camada DAL e não na camada de apresentação.

_______________________________________________________________________
Virei Orculo!
The end is nigh, be ready for the nukes!


#499734 - 27/04/2022 18:26:50

DS2T
BARRA MANSA
Cadast. em:Novembro/2010


@NOWLIGHTS,  estive um pouco ocupado. Estou revivendo esse tópico porque hoje de madrugada eu acho que vou ter um tempinho e faço um exemplo para você.

Abraços

Programo por amor... amor ao dinheiro para pagar as contas...


 Tópico anterior Próximo tópico Novo tópico


Para responder este tópico o login é requerido
Se você já possui uma conta de usuário por favor faça seu login
Se você não possui uma conta de usuário use a opção Criar usuário