You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在多类间共享DbConn实例实现变量访问与数据库操作?

解决DbConn实例共享与代码解耦问题

问题背景

现有三个类:SettingsControl(UserControl)、Main(Form)、DbConn,需求如下:

  • 让SettingsControl设置DbConn中的数据库连接字符串,Main窗体能够读取该字符串
  • DbConn作为数据库操作中间件,统一管理连接凭证并处理所有数据库操作,实现代码解耦

当前核心问题:SettingsControl和Main各自实例化DbConn对象,导致两者无法共享连接字符串。需要实现类似全局实例的效果,同时保证代码符合规范并适配多线程场景。


解决方案

方案1:线程安全的单例模式(快速实现全局共享)

通过单例模式确保整个应用中只有一个DbConn实例,同时通过锁机制保证多线程下的读写安全。

修改DbConn类(线程安全单例)

namespace mySQL_Project
{
    internal class DbConn
    {
        // 静态私有实例,volatile关键字保证多线程下的内存可见性
        private static volatile DbConn _instance;
        // 锁对象,确保线程安全的实例创建与变量读写
        private static readonly object _lockObj = new object();
        
        private string _connString;

        // 私有构造函数,禁止外部直接实例化
        private DbConn() {}

        // 获取全局唯一实例的公共属性
        public static DbConn Instance
        {
            get
            {
                // 双重检查锁定,兼顾线程安全与性能
                if (_instance == null)
                {
                    lock (_lockObj)
                    {
                        if (_instance == null)
                        {
                            _instance = new DbConn();
                        }
                    }
                }
                return _instance;
            }
        }

        // 设置SQLite连接字符串(加锁保证原子性)
        public void SetSQLiteConnString(string connectionString)
        {
            lock (_lockObj)
            {
                _connString = connectionString;
            }
        }

        // 获取SQLite连接字符串(加锁保证读取一致性)
        public string GetSQLiteConnString()
        {
            lock (_lockObj)
            {
                return _connString;
            }
        }

        // 数据库操作示例:查询苹果库存总量
        public int GetSumApples()
        {
            // 每个数据库操作使用独立连接,避免多线程冲突
            using (var conn = new SQLiteConnection(_connString))
            {
                conn.Open();
                using (var cmd = new SQLiteCommand(@"SELECT sum FROM inv WHERE ID=@AI", conn))
                {
                    cmd.Parameters.AddWithValue("@AI", "3");
                    var result = cmd.ExecuteScalar();
                    return result != null ? Convert.ToInt32(result) : 0;
                }
            }
        }
    }
}

修改SettingsControl类(使用单例实例)

namespace mySQL_Project
{
    public partial class SettingsControl : UserControl
    {
        public SettingsControl()
        {
            InitializeComponent();
        }

        private void Button_SetDB_Click(object sender, EventArgs e)
        {
            // 修正:获取TextBox的Text属性
            string connectString = tb_stringtext.Text;
            DbConn.Instance.SetSQLiteConnString(connectString);
        }
    }
}

修改Main类(使用单例实例)

namespace mySQL_Project
{
    public partial class Main : Form
    {
        public Main()
        {
            InitializeComponent();
        }

        private void textBox_getDBConn_Click(object sender, EventArgs e)
        {
            label_dbinfo.Text = DbConn.Instance.GetSQLiteConnString();
        }
    }
}

方案2:依赖注入(推荐中大型项目,解耦性更强)

通过构造函数注入DbConn实例,避免单例带来的全局耦合,同时保证不同组件共享同一个实例,更符合现代软件工程规范。

修改DbConn类(普通类,保留线程安全读写)

namespace mySQL_Project
{
    internal class DbConn
    {
        private string _connString;
        private readonly object _lockObj = new object();

        public void SetSQLiteConnString(string connectionString)
        {
            lock (_lockObj)
            {
                _connString = connectionString;
            }
        }

        public string GetSQLiteConnString()
        {
            lock (_lockObj)
            {
                return _connString;
            }
        }

        public int GetSumApples()
        {
            using (var conn = new SQLiteConnection(_connString))
            {
                conn.Open();
                using (var cmd = new SQLiteCommand(@"SELECT sum FROM inv WHERE ID=@AI", conn))
                {
                    cmd.Parameters.AddWithValue("@AI", "3");
                    var result = cmd.ExecuteScalar();
                    return result != null ? Convert.ToInt32(result) : 0;
                }
            }
        }
    }
}

程序入口(创建共享实例并注入)

namespace mySQL_Project
{
    internal static class Program
    {
        [STAThread]
        static void Main()
        {
            ApplicationConfiguration.Initialize();
            // 创建全局共享的DbConn实例
            var dbConn = new DbConn();
            // 将实例注入Main窗体
            var mainForm = new Main(dbConn);
            // 若SettingsControl在Main中初始化,同步传递该实例
            // var settingsControl = new SettingsControl(dbConn);
            Application.Run(mainForm);
        }
    }
}

修改Main类(构造函数注入)

namespace mySQL_Project
{
    public partial class Main : Form
    {
        private readonly DbConn _dbConn;

        // 通过构造函数接收注入的DbConn实例
        public Main(DbConn dbConn)
        {
            _dbConn = dbConn;
            InitializeComponent();
            // 初始化SettingsControl时传递实例
            // settingsControl = new SettingsControl(_dbConn);
        }

        private void textBox_getDBConn_Click(object sender, EventArgs e)
        {
            label_dbinfo.Text = _dbConn.GetSQLiteConnString();
        }
    }
}

修改SettingsControl类(构造函数注入)

namespace mySQL_Project
{
    public partial class SettingsControl : UserControl
    {
        private readonly DbConn _dbConn;

        // 通过构造函数接收注入的DbConn实例
        public SettingsControl(DbConn dbConn)
        {
            _dbConn = dbConn;
            InitializeComponent();
        }

        private void Button_SetDB_Click(object sender, EventArgs e)
        {
            string connectString = tb_stringtext.Text;
            _dbConn.SetSQLiteConnString(connectString);
        }
    }
}

多线程场景考量

  1. 连接字符串读写:通过lock锁保证读写操作的原子性,避免多线程下的脏读、脏写问题
  2. 数据库连接使用:每个数据库操作创建独立的连接(用using自动释放),不要共享连接对象——SQLite连接本身并非线程安全,ADO.NET连接池会自动处理连接复用
  3. 单例线程安全:双重检查锁定+volatile关键字,确保多线程环境下正确创建唯一实例

方案对比

  • 单例模式:实现简单,适合小型项目快速落地,但会带来一定的代码耦合
  • 依赖注入:解耦性更强,便于单元测试和功能扩展,符合现代软件工程规范,推荐中大型项目使用

内容的提问来源于stack exchange,提问作者ElektrischInkorrekt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 18:14:52