【问题标题】:Managing data access in a simple WinForms app在简单的 WinForms 应用程序中管理数据访问
【发布时间】:2010-12-25 07:00:28
【问题描述】:

我有一个使用 SQLite 的简单 WinForms 数据输入应用程序。它始终是单用户应用程序,并且始终具有本地数据库。我有多个选项卡,用户控件用作选项卡的内容。每次选择一个选项卡时,都会初始化一个适当的 UserControl,并删除旧的(使用 TabPage.Controls.Remove)。

每个 UserControl 初始化一个通用 DataAccess 对象,该对象包装了所有数据库内容,并且可以与任何选项卡内容一起使用。问题是我在选项卡(UserControl)的生命周期内有一个打开的 SQLiteConnection。我在其他地方读到这不是一个好习惯。我不想在设计上过度使用复杂的数据层和业务对象层,部分原因是我不知道该怎么做,部分原因是我认为这个应用程序没有必要这样做。

我基本上将相同的连接、适配器、DataTable、SqlCommand 等对象保留在内存中,并使用不同的 sql 查询参数重用它们,并使用其他方法(如 RowCount)获取缓存的数据。我在使用 LoadData 方法时遇到了问题,因为它没有从 DataTable 中清除以前的查询结果,所以我一开始是手动进行的。

我尝试想办法将“使用”与 SQLiteConnection 和其他对象一起使用,但是对于 RowCount 等简单的事情,我必须重做整个 DataLoad 的东西或类似的东西。因此,我只是在寻找有关这种数据访问方法的建议和 cmets。

下面是我的 DataAccess 类。

public class DataAccess
{
    private SQLiteConnection connection = new SQLiteConnection(Global.DbConnectionString);
    private DataTable dataTable = new DataTable();
    private SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter();
    private SQLiteCommandBuilder commandBuilder = new SQLiteCommandBuilder();
    private SQLiteCommand command = new SQLiteCommand();
    private BindingSource bindingSource = new BindingSource();


    public DataAccess()
    {
        dataAdapter.SelectCommand = command;
        commandBuilder.DataAdapter = dataAdapter;
        bindingSource.DataSource = dataTable;
    }

    ~DataAccess()
    {
        connection.Dispose();
    }

    public BindingSource BindingSource
    {
        get { return bindingSource; }
    }


    ///*
    public void LoadData(string sql, Dictionary<string, string> parameters)
    {
        try
        {
            dataTable.Clear();
            command.Connection = connection;

            // Ignore sql parameter if we already have CommandText. This assumes sql never changes per instance
            if (command.CommandText == null)
                command.CommandText = sql;

            foreach (KeyValuePair<string, string> parameter in parameters)
            {
                if (command.Parameters.Contains(parameter.Key))
                    command.Parameters[parameter.Key].Value = parameter.Value;
                else
                {
                    command.Parameters.Add(new SQLiteParameter(parameter.Key));
                    command.Parameters[parameter.Key].Value = parameter.Value;
                }
            }
            dataAdapter.Fill(dataTable);

        }
        catch (SqlException)
        {
            MessageBox.Show("Data Problem, need to display what's wrong later");
        }

    }//*/

    public int RowCount()
    {
        return dataTable.Rows.Count;
    }

    public string GetFieldValue(int row_index, string column_name)
    {
        return dataTable.Rows[row_index][column_name].ToString();
    }

    public void Save()
    {
        dataAdapter.Update(dataTable);
    }

    public void NewRow(Dictionary<string, string> fields)
    {
       DataRow dataRow = dataTable.NewRow();

        foreach (KeyValuePair<string, string> field in fields)
            dataRow[field.Key] = field.Value;

        dataTable.Rows.Add(dataRow);
    }
}

【问题讨论】:

  • 通过这种设计,您可以对您的应用程序进行单元测试吗?
  • 不,甚至还没有考虑单元测试。

标签: c# winforms sqlite datatable sqlconnection


【解决方案1】:

如果您想做得很好,您应该创建一个数据访问层,该层将公开获取数据和修改数据的方法。该层会在必要时打开一个连接,然后关闭它。您可以在其上添加一个缓存层。而且您的 GUI 只会使用来自较低层的数据对象。

这不是一个小的重写,所以如果您当前的解决方案有效,并且您不想在它上面投入太多精力,那么就这样吧,这还不错。如果是一个简单的程序,那么这个简单的解决方案就可以了。

【讨论】:

  • 谢谢,您知道我可以查看的此类应用的任何示例吗?
猜你喜欢
  • 2011-10-22
  • 2011-02-03
  • 2015-04-12
  • 2019-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多