Pergunta

Eu tenho uma situação muito comum aqui. E durante anos eu não encontrei, se o que eu estou fazendo é certo pela indústria standards.Consider uma aplicação que se conecta ao banco de dados, mas onde a seqüência de conexão em vez de ser armazenado em algum arquivo / configuração está sendo passado como um parâmetro de linha de comando durante a inicialização ou o banco de dados é consultada para no momento que o aplicativo é iniciado.

Bem, torna-se necessário para salvar que em algum lugar seqüência de conexão dentro do escopo do aplicativo. A forma mais comum que tenho visto isto ser feito é um módulo ou classe global com métodos get / set para salvar a seqüência de conexões. Outra maneira que eu iria fazê-lo é usando Singleton. Tanto opções meu DAL pode acessar a string de conexão quando ele precisa através de um método GetConnectionString.

Existe uma maneira melhor de fazer isso?

Update: eu não tenho um arquivo de configuração e até mesmo se eu fiz eu precisaria a seqüência de conexão para ser lido uma vez para a vida da instância do aplicativo. você pode elaborar sobre a parte "injetá-lo em todas as classes"

Foi útil?

Solução

Em estado global geral, seja uma classe global ou um singleton, deve ser evitado sempre que possível.

A solução ideal seria ter sua carga de aplicação até a seqüência de conexão fora do config e injetar -lo em todas as classes que necessitam. Dependendo do tamanho da sua aplicação, uma href="http://en.wikipedia.org/wiki/Inversion_of_control" rel="noreferrer"> IoC recipiente Unidade ou Castelo de Windsor pode ajudar, mas certamente não é uma parte necessária de solução.

Se isso não é uma opção e você está preso manter o estado global (por causa da base de código existente ou o que for), eu não sei que há uma enorme diferença entre as duas abordagens que você sugeriu.

Update: Só para esclarecer, esquecer todo o material sobre recipientes de IoC, por agora, "Inject" é apenas uma maneira elegante de dizer "passar como um parâmetro" (tanto para o construtor da classe, ou através de uma propriedade, ou qualquer outro).

Ao invés de ter uma classe de acesso de dados tem que perguntar para a seqüência de conexão (de algum tipo de global ou um singleton), já passou na via o construtor ou uma propriedade.

Atualização # 2:. eu acho que ainda há algum mal-entendido quanto ao que esta abordagem implica

É basicamente se resume a saber se seus dados olhares classe de acesso como:

public class DataAccessClass
{
    public DataAccessClass()
    {
        _connString = SomeStaticThing.GetConnectionString();
    }
}

ou

public class DataAccessClass
{
    public DataAccessClass(string connString)
    {
        _connString = connString;
    }
}

Estes artigos (e, de fato, muitos dos artigos em que o blog ) detalhe uma série de razões pelas quais a última é melhor do que o anterior (até porque o primeiro é quase impossível de teste de unidade).

Sim, no algum lugar não vai ter que haver alguma estática cara responsável por pegar a string de conexão, em primeiro lugar, mas o ponto é que suas dependências em métodos estáticos são limitados a esse um ponto (que é provavelmente vai ser o seu método principal no processo de bootstrapping sua aplicação), ao invés de espalhados por toda a sua base de código.

Outras dicas

É bom ver tantas soluções criativas para um problema tão simples; -)

fatos salientes, a partir questão OP:

  1. Conectar-string é passado na linha de comando
  2. muitos outros componentes pode precisar usar o connect-string

assim, não há nenhuma maneira em torno do uso de um elemento estático ; se é uma variável global (difícil de fazer em .NET, realmente, sem uma classe delimitador), uma classe estática ou um singleton realmente não importa. A solução caminho mais curto seria uma classe estática inicializada pela classe programa que processou a linha de comando.

Cada outra solução ainda exigiria o acesso estático para o passado-in connect-string , embora possam esconder isso atrás de uma ou mais camadas de engano.

Eu não estou dizendo que você não quer vestir-se a solução básica com algo mais extravagante, mas não é necessário, e isso não elimina a natureza fundamentalmente estático / global da conexão-string como descrito .

Se tudo que você está armazenando é uma string (possivelmente junto com um monte de outras configurações de aplicativos globais), eu iria usar apenas uma classe estática com um monte de propriedades para segurar tudo isso. Um singleton é mais código e manutenção trabalho, mas é um trabalho necessário, neste caso, uma vez que sua classe propriedades não vai fazer qualquer coisa; apenas segurar as coisas.

Claro que há um caminho. Primeiro, chegar até a velocidade na rel="nofollow noreferrer"> injeção de dependência e técnicas semelhantes, e ler sobre serviço de camada já que é o que você precisa aqui.

Tanto quanto uma camada de serviço está em causa, você precisa de algum tipo de serviço de configuração, que será o módulo que partes do seu aplicativo irá consultar informações de configuração - seqüências de conexão, URIs, etc:

interface IConfigurationService
    string ConnectionString
    bool IntegratedSecurity
    bool EncryptProfiles

Deve ser bastante simples de que há apenas uma instância de IConfigurationService em seu sistema, mas isso é conseguido com um recipiente DI de escolha, não com padrão Singleton.

Em seguida, todos os seus serviços DAL vai ter uma referência para o IConfigurationService:

class FooDal : IFooDal
    IConfigurationService ConfigurationService

de modo que agora eles podem usar IConfigurationService.ConnectionString para se apossar da cadeia de ligação.

Depende.

Tenha em mente que um singleton:

  • Impõe que exatamente uma instância da classe existirão, e
  • fornece acesso global

A global só fornece acesso global, mas não faz nenhuma garantia sobre o número de instâncias.

E a última opção, é claro, é usar uma variável local. Ou seja, passar a informação de configuração em torno de como um parâmetro para o construtor ou onde quer que seja necessário.

A escolha entre os dois primeiros deve ser um pouco fácil. É um desastre se duas instâncias da exist classe? Eu diria que provavelmente não. I pode querer instanciar minha própria classe de configuração para fornecer opções separadas para um componente específico do aplicativo, ou para inicializar os meus testes unitários.

Há muito poucos casos em que você necessidade para garantia de que exatamente uma instância existirão. Por esta razão, a global pode ser uma escolha melhor do que um singleton.

A escolha entre o local eo global é mais complicado. estado mutável global é geralmente melhor evitar. Imutável estado é menos de um problema, e não vai levar aos mesmos problemas de sincronização / simultaneidade / escalabilidade que o estado mutável global.

Mas, muitas vezes, pode ser preferível tê-lo como uma variável local que você passa ao redor para os componentes que necessitam. Isso pode ser feito manualmente, basta passá-lo para o construtor de um objeto que precisa de acesso DB, ou pode até certo ponto ser automatizada com um contêiner IoC.

Mas em qualquer caso, se não é global, então o seu código se torna mais genérico, e mais portátil. Se ele tem escondido dependências em classes e dados globais que deve existe para o código para o trabalho, então não pode ser facilmente usado em outros projetos, ou se você refatorar toda a base de código muito.

Ele também se torna mais difícil de teste de unidade, de novo, porque o código não vai mesmo compilar a menos que exista alguma dados externos que nós idealmente como deixar de fora do nosso teste.

como disse @Anton, você precisa ter uma interface que expõe algo como

interface IConfigurationService
    string ConnectionString

Em seguida, sempre que um de sua classe precisa de sua cadeia de conexão, você fornecê-lo com uma implementação de IConfigurationService sobre a construção que contém a cadeia de caracteres válida. Você precisa encontrar um lugar válido para criar a sua aplicação quando app começa (provavelmente o momento onde você poderá obter o seu endereço de banco de dados), e passá-lo para a classe precisar dele.

Mesmo que possa parece um monte de trabalho em comparação com única ou global, isso vai diminuir o acoplamento em seu código, portanto, melhorar a capacidade de reutilização e unidade de tornar o teste mais fácil, e é bastante simples uma vez que você se convencer de que globals são (principalmente) o mal; )

Como mencionada antes, há IoC recipiente que irá fornecer a estrutura para fazer isso, mas pode ser um exagero no seu caso, além de sua agradável de usar o padrão para si mesmo antes de deixar o trabalho para uma "caixa mágica"

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top