我正在尝试制作一个C#GUI来编辑SQLite数据库。当我使用SQLiteDataAdapter填充DataGridView时,数据显示不正确:
SQLiteDataAdapter错误地加载了数据,因此数据在到达演示者时就不正确。有关SQLite数据类型的信息,请参见this。
这是我在演示者中加载表格的代码(我遵循带有被动视图的MVP设计模式):
//Presenter method
private void BindData()
{
DataTable entireTable = _model.GetEntireTable(GetTableName());
//_screen is the View (actual form) of the program
//_screen.MainTableDataSource is a BindingSource
//_screen.MainTable is a DataGridView
_screen.MainTableDataSource.DataSource = entireTable;
_screen.MainTable.DataSource = _screen.MainTableDataSource;
}
//Model method
public DataTable GetEntireTable(string tableName)
{
string query = "SELECT rowid, * FROM " + tableName;
_dataAdapter = new SQLiteDataAdapter(query, _connection);
_dt = new DataTable();
_dataAdapter.Fill(_dt);
return _dt;
}
到目前为止我尝试过的解决方案:
由于复杂性,我曾经尝试过但尚未尝试实现的另一个想法:
我担心这最后一个选项会创建复杂的代码并导致过滤问题。我的客户希望能够快速将过滤器应用于表格。现在,我正在使用BindingSource进行过滤,与将查询发送到SQLite相比,这是非常快的。
我是否缺少某些东西或是否没有优雅的方法来处理C#中混合类型的SQLite数据库?我已经花了数小时搜寻网路,却找不到任何有类似问题的人。
编辑:我应该补充一点,我正在使用System.Data.SQLite。
答案 0 :(得分:0)
这不是很漂亮,但是对于那些感兴趣的人,我想出了一种解决方法。
这是从数据库中初始加载后调用的 Presenter 方法:
//Presenter method called after initial load from database
private void CheckDataBaseForWrongTypes(string table)
{
foreach (DataGridViewColumn col in _table.Columns)
{
col.ValueType = typeof(string);
}
DataTable typeCheckerDT = _model.GetSchemaForCurrentTable(table);
int i = -1;
foreach (DataRow row in typeCheckerDT.Rows)
{
i++;
string col = Convert.ToString(row.ItemArray[1]);
string type = Convert.ToString(row.ItemArray[2]);
if (type.Equals("TEXT") || type.Equals("BLOB")) //Columns of this type will always display correctly, as far as I know
{
continue;
}
//Correct values in numeric field that are actually stored as strings in database
DataTable invalidTable = _model.GetNonNumericDataInSpecifiedColumn(table, col);
DataTable dt = _model.GetMainTableDT();
dt.PrimaryKey = new DataColumn[] { dt.Columns["rowid"] };
foreach (DataRow invalidRow in invalidTable.Rows)
{
int rowPrimaryKey = Convert.ToInt32(invalidRow.ItemArray[0]);
DataRow rowToModifyType = dt.Rows.Find(rowPrimaryKey);
int index = dt.Rows.IndexOf(rowToModifyType);
_table.Rows[index].Cells[i + 1].Value = _model.GetActualDataBaseStringValueInANumericColumn(_table.Name, rowPrimaryKey, col);
}
if (type.Equals("REAL") || type.Equals("NUMERIC")) //Decimals will only be displayed incorrectly in integer columns
{
continue;
}
//Correct values in integer field that are actually decimals
invalidTable = _model.GetDecimalDataInSpecifiedColumn(table, col);
dt = _model.GetMainTableDT();
dt.PrimaryKey = new DataColumn[] { dt.Columns["rowid"] };
foreach (DataRow invalidRow in invalidTable.Rows)
{
int rowPrimaryKey = Convert.ToInt32(invalidRow.ItemArray[0]);
DataRow rowToModifyType = dt.Rows.Find(rowPrimaryKey);
int index = dt.Rows.IndexOf(rowToModifyType);
_table.Rows[index].Cells[i + 1].Value = _model.GetActualDataBaseRealValueInAnIntegerColumn(_table.Name, rowPrimaryKey, col);
}
}
}
以下是模型中查询数据库的方法:
public DataTable GetNonNumericDataInSpecifiedColumn(string table, string col)
{
string query = "SELECT rowid, * FROM " + table + " WHERE [" + col + "] GLOB '*[^0123456789.-]*'";
return FetchDTFromDatabase(query);
}
public DataTable GetDecimalDataInSpecifiedColumn(string table, string col)
{
string query = "SELECT rowid, * FROM " + table + " WHERE [" + col + "] NOT GLOB '*[a-zA-Z]*' AND [" + col + "] GLOB '*.*';";
return FetchDTFromDatabase(query);
}
public string GetActualDataBaseStringValueInANumericColumn(string table, int rowPrimaryKey, string colName)
{
string query = "SELECT [" + colName + "] FROM " + table + " WHERE rowid=" + rowPrimaryKey + ";";
using (SQLiteCommand cmd = new SQLiteCommand(query, _connection))
{
using (SQLiteDataReader reader = cmd.ExecuteReader())
{
reader.Read();
string value = reader.GetString(0);
return value;
}
}
}
public string GetActualDataBaseRealValueInAnIntegerColumn(string table, int rowPrimaryKey, string colName)
{
string query = "SELECT [" + colName + "] FROM " + table + " WHERE rowid=" + rowPrimaryKey + ";";
using (SQLiteCommand cmd = new SQLiteCommand(query, _connection))
{
using (SQLiteDataReader reader = cmd.ExecuteReader())
{
reader.Read();
double value = reader.GetDouble(0);
return value.ToString();
}
}
}
private DataTable FetchDTFromDatabase(string query)
{
SQLiteDataAdapter adapter = new SQLiteDataAdapter(query, _connection);
DataTable table = new DataTable();
adapter.Fill(table);
return table;
}
再次,这确实是一种解决方法,对于那些制作消费者级应用程序的人(我只是在开发工具),这不是一个干净的解决方案。