接上篇《TreeView的数据源绑定—采用XML作为数据源,实现对treeview进行增删改查,之后回写XML文档》,本篇是使用一种比较轻型的数据库—sqlite作为treeview的数据源,关于sqlite具体的知识请前往:
1,sqlite官网
2,维基百科
3,百度百科
根据当前项目存储的要求,由于之前使用XML来存储,现在再用XML有些不方便,时间上花费要多,所以在网上找了sqlite作为新的数据存储源,使用之后,感觉实在是太方便了,所以把使用过程记录下来,本人作为第一次用sqlite,对以前没接触过sqlite的朋友来说,可以参考参考的,但毕竟是我一个人的思想,所以,写的不好,还请大家不要见怪!
首先,得先讲下sqlite的优点:使用简单,不需要安装配置,拿到.db文件就可以用,蒽,很适合存储量比较小的winfrom程序(如我当前的这个项目),最重要的是sqlite开源而还且免费的哦,还有其他很多的优点,现在讲到的都是我现在已经用到了;
当然,毕竟没有完美的事物,缺点:存储的数据量不大,大家用的时候不要当作MSSQL、MYSQL或ORACLE来用,据说,最大可以达到2TB,不知道是不是真的。- -!性能嘛,当然是数据量越小的时候,发挥的越好,反正我用到现在查询速度还是可以的,够用就行了。
使用的时候装个管理工具吧,我推荐我现在使用的这款,是免费的,SQLite可视化数据库管理器。
在项目中还需要引用来自外部的2个DLL文件,我把文件放在了附件中。
使用sqlite的时候,我的项目中新建了一个类,该类专门处理来自窗体页面的查询,类似与SQLHelper,我把主要的查询函数贴上来,具体的我会作为附件,请需要的朋友下载附件查看。
/// <summary>
/// 创建SQL语句和插入SQL语句
/// </summary>
/// <param name="sqlStr">SQL语句</param>
public void ExecuteCreate(string sqlStr)
{
using (DbConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
DbCommand comm = conn.CreateCommand();
comm.CommandText = sqlStr;
comm.CommandType = CommandType.Text;
comm.ExecuteNonQuery();
}
}
/// <summary>
/// 执行查询
/// </summary>
/// <param name="sqlStr">SQL语句</param>
public string ExecQuery(string sqlStr)
{
string text = string.Empty;
using (DbConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
DbCommand comm = conn.CreateCommand();
comm.CommandText = sqlStr;
comm.CommandType = CommandType.Text;
using (IDataReader reader = comm.ExecuteReader())
{
while (reader.Read())
{
text = reader[0].ToString();
}
}
}
return text;
}
/// <summary>
/// 修改数据库的语句
/// </summary>
/// <param name="strSql">需要修改SQL语句</param>
public void ExecuteModity(string strSql)
{
using (DbConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
DbCommand comm = conn.CreateCommand();
comm.CommandText = strSql;
comm.CommandType = CommandType.Text;
comm.ExecuteNonQuery();
}
}
/// <summary>
/// 删除数据库中的数据
/// </summary>
/// <param name="strSql"></param>
public void ExecuteRemove(string strSql)
{
using (DbConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
DbCommand comm = conn.CreateCommand();
comm.CommandText = strSql;
comm.CommandType = CommandType.Text;
comm.ExecuteNonQuery();
}
}
/// <summary>
/// 执行查询返回DataSet
/// </summary>
/// <param name="sqlStr">SQL语句</param>
/// <returns>返回DataSet</returns>
public DataSet ExecDataSet(string sqlStr)
{
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
conn.Open();
SQLiteCommand cmd = conn.CreateCommand();
cmd.CommandText = sqlStr;
cmd.CommandType = CommandType.Text;
DataSet ds = new DataSet();
SQLiteDataAdapter da = new SQLiteDataAdapter(cmd);
da.Fill(ds);
return ds;
//conn.Close();
}
}
查询sqlite的数据,然后绑定到treeview控件
/// <summary>
/// 绑定sqlite的数据
/// </summary>
private void SelectData()
{
string dbPath = "Area_db.db";
SqliteHelper sh = new SqliteHelper(dbPath);
//string sql = "select * from AreaTree";
AddTreeView(0, (TreeNode)null);
}
private void AddTreeView(int parentId, TreeNode parentNode)
{
try
{
string strPath = "Area_db.db";
string sql = "select * from AreaTree";
SqliteHelper sh = new SqliteHelper(strPath);
DataView dv = new DataView(sh.ExecDataSet(sql).Tables[0]);
string strFile = "a_Parent=" + parentId;
dv.RowFilter = strFile;
foreach (DataRowView row in dv)
{
TreeNode node = new TreeNode();
//处理根节点
if (parentId == 0)
{
node.Name = row["a_Id"].ToString();
node.Text = row["a_Name"].ToString();
tree_Area.Nodes.Add(node);
AddTreeView(Int32.Parse(row["a_Id"].ToString().Trim()), node);
}
//处理子节点
else
{
node.Name = row["a_Id"].ToString();
node.Text = row["a_Name"].ToString();
parentNode.Nodes.Add(node);
AddTreeView(Int32.Parse(row["a_Id"].ToString().Trim()), node);
}
}
tree_Area.ExpandAll();
}
catch { }
}
修改treeview结构,保存到sqlite,这几个函数和使用MSSQL是一样的,和ADO.NET很像,所以这里也就直接贴出代码了,欢迎私下讨论。
private void ModifyTreeView()
{
try
{
string dbPath = "Area_db.db";
string strAreaName = txt_AreaName.Text.Trim();
string strNub = txt_Nub.Text.Trim();
SqliteHelper sh = new SqliteHelper(dbPath);
string sql = string.Empty;
if (TextBoxValidator(strAreaName))
{
MessageBox.Show("请输入地区或设备名称 !", "提示");
txt_AreaName.Focus();
}
else if (TextBoxValidator(strNub))
{
MessageBox.Show("请输入该地区或设备的逻辑地址 !", "提示");
txt_Nub.Focus();
}
else
{
sql = "update AreaTree set a_Name='" + strAreaName + "',a_Value='" + strNub + "' where a_Id=" + tree_Area.SelectedNode.Name + "";
sh.ExecuteModity(sql);
tree_Area.Nodes.Clear();
AddTreeView(0, (TreeNode)null);
}
}
catch { }
}
删除节点,这里有个情况,如果删除多个,就是删除的节点中还有子节点的话,该如何操作,是把当前选中节点全部删掉,还是让用户只删除一个,这就看个人的需求了,我项目中的是只让客户删除不超过2级的节点。
private void RemoveTreeView()
{
if (tree_Area.SelectedNode != null)
{
TreeNode node = tree_Area.SelectedNode;
int childNode = node.Nodes.Count;
if (childNode == 0)
{
DeleteTreeNode(node);
}
else
{
if (MessageBox.Show("确定要删除选中的所有节点吗 ?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
DeleteTreeNode(node);
}
}
}
else
{
MessageBox.Show("未选中节点,请选中需要删除的节点!", "提示");
}
}
/// <summary>
/// 删除所选节点及其子节点,同时更新数据库
/// </summary>
/// <param name="parentNode"></param>
private void DeleteTreeNode(TreeNode parentNode)
{
try
{
//获取当前删除的节点是否还有子节点
int childCount = parentNode.Nodes.Count;
for (int i = 0; i < childCount; i++)
{
TreeNode childNode = parentNode.Nodes[0];
if (childNode.Nodes.Count > 0)
{
DeleteTreeNode(childNode);
}
else
{
DeleteTreeNode(childNode);
childNode.Remove();
}
}
if (parentNode.Nodes.Count == 0)
{
DeleteNodeData(parentNode);
parentNode.Remove();
}
}
catch { }
}
/// <summary>
/// 在数据库中删除当前选中的节点
/// </summary>
/// <param name="node"></param>
private void DeleteNodeData(TreeNode node)
{
string strPath = "Area_db.db";
SqliteHelper sh = new SqliteHelper(strPath);
string sql = string.Empty;
sql = "delete from AreaTree where a_Id="+node.Name+"";
sh.ExecuteRemove(sql);
}
蒽,还有个情况是,关于sqlite管理器的字符编码问题,在sqlite管理器中一般都以UFT-8编码显示,但是在C#中,所有字符窜的编码都是unicode,写入的时候应该注意编码转换问题,我这边是出现了字符编码的问题,后面写了个函数来转换。在连接sqlite的时候可以写明需要操作的是什么编码,编译环境会自动根据设定的字符编码来get、set,显示也就正常了,如果,在sqlite管理工具上查看的是uft-8编码的话,那取出的数据也应该是显示正常的,但是在有的PC上显示的是乱码,这个时候就应该去转换一下,读取的数据了。
/// <summary>
/// 把GB转换成uft8-8
/// </summary>
/// <param name="strEnCode"></param>
private string EnCodeing(string strEnCode)
{
UTF8Encoding uft8 = new UTF8Encoding();
string unicodeString = strEnCode;
Byte[] encodeBytes = uft8.GetBytes(unicodeString);
String decodeString = uft8.GetString(encodeBytes);
return decodeString;
}
程序运行效果图:
总结:我这边写的数据库语句全是拼接的,但是在逛论坛的时候,看到说数据库的语句要少用字符窜拼接的形式,但是,我不知道该怎么去解决他,所以,还请各位知道的前辈告知下,谢谢!这次的sqlite学习旅途比较愉快的,主要是刚接触,比较有兴趣,还有就是sqlite的数据库语法和MSSQL很像,比较快上手。 Via cnblogs.com/aehoo/ 2012-02-27 WJF Dev
附件的内容有:1,System.Data.SQLite.DLL 使用sqlite必要的文件
2,System.Data.SQLite.Linq.dll 使用sqlite必要的文件
3,SqliteHelper.cs 被我称为数据库操作类
4,SQLiteTest 一个测试demo
点击下载附件:下载