C# 自定义数据库连接对象:我应该使用通用的(单例)还是每个对象实例一个?

C# 自定义数据库连接对象:我应该使用通用的(单例)还是每个对象实例一个?,c#,repository-pattern,dao,data-access-layer,data-access,C#,Repository Pattern,Dao,Data Access Layer,Data Access,最佳实践是什么:只创建一个静态类(Singleton)来提供到数据库的所有必要连接,或者为每个DAO实例创建一个对象? 请注意,我的项目同时访问多个数据库,因此我创建了一个类AcessoBanco,该类接收.INI配置文件,并返回我需要的所有连接。 我使用的是单一静态类方法,但由于系统执行一些多线程任务,我收到了关于并发性的零星异常。我通过在AcessoBanco类中创建锁解决了这个问题,但是,这真的是个好主意吗? 也许,如果我将AcessoBanco的一个实例放在每个dao对象上,并发问题就可

最佳实践是什么:只创建一个静态类(Singleton)来提供到数据库的所有必要连接,或者为每个DAO实例创建一个对象? 请注意,我的项目同时访问多个数据库,因此我创建了一个类
AcessoBanco
,该类接收.INI配置文件,并返回我需要的所有连接。 我使用的是单一静态类方法,但由于系统执行一些多线程任务,我收到了关于并发性的零星异常。我通过在
AcessoBanco
类中创建锁解决了这个问题,但是,这真的是个好主意吗? 也许,如果我将
AcessoBanco
的一个实例放在每个dao对象上,并发问题就可以更优雅地解决,对吗?一些例子:

使用单例方法

public class Repository1
{
    public Repository1(string iniFilePath)
    {
        AcessoBanco.Configure(iniFilePath); // Singleton that creates all the connections (concurrency excepction solved using locks)

        // After configured, just call AcessoBanco.GetConnections() in any point of the code to get the connections 
    }
}
每个对象使用一个实例

public class Repository2
{
    public AcessoBanco Conexoes { get; set; }
    public Repository2(string iniFilePath)
    {
        Conexoes = new AcessoBanco(iniFilePath); // Using one instance of AcessoBanco in each DAO. I will need to do it in every DAO.
    }
}

这在很大程度上取决于您使用哪种db

仅举两个例子:

  • CosmosDB
    -建议使用客户机的单例实例,因为它使用(最常见的)http调用,类似于
    HttpClient
    单例实例
  • ADO.NET
    (对于sql server)-使用单实例是一个非常糟糕的主意,因为您的应用程序可能需要使用来自不同线程的连接,并且您将遇到一大堆不同的问题。这就是为什么它在引擎盖下使用连接池

  • 您提供的详细信息并不表明使用单例模式是一个好主意;相反,正如您已经发现的,它可能会导致多线程应用程序出现问题。大多数数据库引擎支持连接池,打开/关闭连接的开销应该最小。也不要提前打开连接。只需在您严格需要的时间打开/关闭连接。你正在制造比你需要的更多的头痛

    这样或类似的模式没有什么问题:

    using (var connection = new Connection()){
    
    }
    

    是的,我同意,但是我的应用程序用户需要一个可变数量的数据库,我需要提前知道可用数据库的列表。
    AcessoBanco
    类为我评估一个.ini文件。我的问题是:我只需要创建一次可用数据库的列表(例如:在应用程序启动时),或者每次需要连接时创建一次可用数据库的列表。我使用SQL Server。那么,每个实例一个连接,对吗?每个什么实例?每个需要访问de数据库的对象实例(我的dao),每个需要访问数据库的对象都有自己的
    AcessoBanco
    实例。我们谈论的是同一件事?不。您希望尽可能晚地打开连接,并尽可能早地关闭它。这意味着要么使用
    open()
    close()
    ,要么如@Icarus所述,使用
    块。