Pergunta

queria saber se ele é recomendado para passar um objeto de conexão de banco de dados ao redor (para outros módulos) ou deixar que o método (em outro módulo) cuidar de sua criação. Estou inclinado a deixar o método de configurá-lo para não ter que verificar o estado da conexão antes de usá-lo, e apenas ter o chamador passar todos os dados necessários para o método chamando o que seria necessário para configurar a conexão.

Foi útil?

Solução

Pessoalmente eu gosto de usar conexões firmemente escopo; abri-los tarde, usá-los e fechá-los (em um "usando" bloco, tudo dentro do método de local). pool de conexão vai lidar com re-utilizando a ligação na maioria dos casos, para que não haja sobrecarga real nesta abordagem.

A principal vantagem de passagem conexões usado para ser de modo que você poderia passar a transação ao redor; no entanto, TransactionScope é uma maneira simples de compartilhar uma transação entre os métodos.

Uma vez que as classes são a implementação específica, eu ia escrever cada um para abrir a sua própria transação nativa. Caso contrário, você pode usar os métodos ado.net fábrica para criar o tipo apropriado do arquivo de configuração (o nome do fornecedor).

Outras dicas

Pessoalmente, eu gosto de guardar uma pilha de minha conexão aberta atual e transações no topo do thread local armazenamento usando SetData e GetData. I definir uma classe que gerencia minhas conexões com o banco de dados e permitir que ele use o padrão de descarte. Isto poupa-me a necessidade de passar conexões e transações ao redor, que é algo que eu acho que tumultua e complica o código.

Eu recomendaria fortemente contra deixá-lo até os métodos para conexões abertas cada vez que eles precisam de dados. Vai leva a uma situação muito ruim, onde é tanto difícil de gerir as operações em todo o aplicativo e muitas conexões são abertos e fechados (eu sei sobre o pool de conexão, ainda é mais caro para procurar uma conexão do pool do que é a reutilização de um objeto)

Então eu acabar tendo algo ao longo destas linhas (totalmente não testado):

class DatabaseContext : IDisposable {

    List<DatabaseContext> currentContexts;
    SqlConnection connection;
    bool first = false; 

    DatabaseContext (List<DatabaseContext> contexts)
    {
        currentContexts = contexts;
        if (contexts.Count == 0)
        {
            connection = new SqlConnection(); // fill in info 
            connection.Open();
            first = true;
        }
        else
        {
            connection = contexts.First().connection;
        }

        contexts.Add(this);
    }

   static List<DatabaseContext> DatabaseContexts {
        get
        {
            var contexts = CallContext.GetData("contexts") as List<DatabaseContext>;
            if (contexts == null)
            {
                contexts = new List<DatabaseContext>();
                CallContext.SetData("contexts", contexts);
            }
            return contexts;
        }
    }

    public static DatabaseContext GetOpenConnection() 
    {
        return new DatabaseContext(DatabaseContexts);
    }


    public SqlCommand CreateCommand(string sql)
    {
        var cmd = new SqlCommand(sql);
        cmd.Connection = connection;
        return cmd;
    }

    public void Dispose()
    {
        if (first)
        {
            connection.Close();
        }
        currentContexts.Remove(this);
    }
}



void Test()
{
    // connection is opened here
    using (var ctx = DatabaseContext.GetOpenConnection())
    {
        using (var cmd = ctx.CreateCommand("select 1"))
        {
            cmd.ExecuteNonQuery(); 
        }

        Test2(); 
    }
    // closed after dispose
}

void Test2()
{
    // reuse existing connection 
    using (var ctx = DatabaseContext.GetOpenConnection())
    {
        using (var cmd = ctx.CreateCommand("select 2"))
        {
            cmd.ExecuteNonQuery();
        }
    }
    // leaves connection open
}

Para fins de testes automatizados, é geralmente mais fácil de passá-lo. Isso é chamado injeção de dependência .

Quando você precisa escrever testes, você pode criar um objeto de conexão de banco de dados de simulação e passar essa vez do real. Dessa forma, seus testes automatizados não vai contar com um banco de dados real que precisa ser repovoada com os dados de cada vez.

Eu pessoalmente trabalhar para centralizar o meu acesso a dados, tanto quanto possível, no entanto, se não for possível eu abrir sempre uma nova conexão nas outras classes, como eu descobrir que existem muitas outras coisas que podem ficar no caminho ao passar o objeto de conexão real.

Aqui é um pouco mais conhecimento sobre este problema. Eu tenho uma classe que gerencia conexões db, e tenho 2 classes que implementam uma interface. Uma das classes é para SQL eo outro é de OLAP. O gerente é aquele que sabe qual conexão utilizar, para que ele pudesse passar a conexão exata com o tipo ou o tipo pode criar sua própria conexão.

Você pode passar objetos de conexão sem qualquer problema (por exemplo, Microsoft Enterprise Library permite chamadas de métodos estáticos que passam em uma ligação) ou você pode gerenciá-lo externamente cabe a seu projeto, há vantagens e desvantagens técnicas não diretos.

Tenha cuidado para portabilidade para não passar uma conexão específica, se sua solução irá ser portado para outras bases de dados (ou seja, NÃO FAZEM passar um SqlConnection que você pretende trabalhar com outros bancos de dados)

Configurando a conexão é potencialmente caro e potencialmente adiciona uma ida e volta. Então, novamente, potencialmente, o projeto melhor é passar o objeto de conexão.

Eu digo potencialmente, porque se você é um aplicativo Microsoft ADO, você provavelmente está usando um pool de conexão ....

Gostaria de sugerir que você distinguir entre o objeto de conexão e seu estado (aberto, fechado).

Você pode ter um único método (ou propriedade) que lê a seqüência de conexão de web.config. Usando a mesma versão da seqüência de conexão cada vez que garante que você vai beneficiar de pool de conexão.

Chamar esse método quando você precisa para abrir uma conexão. No último momento, depois de configurar todas as propriedades SqlCommand, abrir a conexão, usá-lo, e depois fechá-lo. Em C #, você pode usar a instrução usando para garantir que a conexão é fechada. Se não, certifique-se de fechar a conexão em um bloco finally.

Eu usaria o web.config

<configuration>
    <connectionStrings>
        <add name="conn1" providerName="System.Data.SqlClient" connectionString="string here" />
        <add name="conn2" providerName="System.Data.SqlClient" connectionString="string here" />
    </connectionStrings>
</configuration>

Depois, você pode referenciá-lo de qualquer lugar do aplicativo

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