前言

客户端存储信息的方法有好多种,在以往的项目中采用的是序列化记录到文件中的方式,即时通信项目中客户端的一些系统配置的保存也使用的这种方式,然而客户端保存聊天记录就不能使用这种方式(保存、读取、修改都需要进行序列化操作比较费时,不同会话聊天记录到不同文件中,将需要创建大量的文件),调研相关技术后,决定使用SQLite。

SQLite

我的认知如下:
SQLite是一款轻量级文件数据库,无需部署安装,特点是嵌入式与事务(原子性、一致性、隔离性和持久性)。使用时只需创建一个db文件(db文件即代表一个数据库),然后利用ADO.NET进行连接库、创建、插入、查询、修改表就可以了,非常的简单方便。

步骤

1.添加引用
右键项目引用选择 管理Nuget程序包 搜索SQLite,选择第一个进行安装

2.创建数据库文件

string dbPath = AppDomain.CurrentDomain.BaseDirectory + "local.db";
SQLiteConnection.CreateFile(dbPath);

注意需要添加引用:using System.Data.SQLite;
3.连接SQLite

SQLiteConnection conn = new SQLiteConnection();
SQLiteConnectionStringBuilder connstr = new SQLiteConnectionStringBuilder();
connstr.DataSource = datasource;
connstr.Password = "";//设置密码,SQLite ADO.NET实现了数据库密码保护
conn.ConnectionString = connstr.ToString();
conn.Open();

4.创建表

SQLiteCommand cmd = new SQLiteCommand();
string sql = "CREATE TABLE FirstTable(ID varchar(36),UserName varchar(30),PassWord varchar(30))";
cmd.CommandText = sql;
cmd.Connection = conn;
cmd.ExecuteNonQuery();

5.增删改查
增:

SQLiteCommand cmd = new SQLiteCommand();
string sql = "INSERT INTO FirstTable VALUES('1','ading3','123')";
cmd.Connection = conn;
cmd.CommandText = sql;
cmd.ExecuteNonQuery();

删:

string sql = "DELETE FROM FirstTable WHERE ID = @ID";
SQLiteParameter[] parms =
{
new SQLiteParameter("@ID",id)
};
command.CommandText = sql;
command.Parameters.AddRange(parameters);
int counts = command.ExecuteNonQuery();

改:

string sql= @"UPDATE FirstTable
SET UserName=@UserName,
PassWord=@PassWord
WHERE UserName='admin'
";
SQLiteParameter[] parms1 =
{
new SQLiteParameter("@UserName","adminading"),
new SQLiteParameter("@PassWord","")
};
command.CommandText = sql;
command.Parameters.AddRange(parameters);
int counts = command.ExecuteNonQuery();

查:

string query = "SELECT * FROM FirstTable";
DataTable dt = SQLiteHelper.ExecuteQuery(query, null);
List<Test> tlist = new List<Test>();
foreach (var item in dt1.Rows)
{
Test tt = new Test();
tt.ID=(item as DataRow)["ID"].ToString();
tt.UserName = (item as DataRow)["UserName"].ToString();
tt.PassWord = (item as DataRow)["PassWord"].ToString(); tlist.Add(tt);
}
public class Test
{
public string ID { get; set; }
public string UserName { get; set; }
public string PassWord { get; set; }
}

帮助类

  /// <summary>
/// SQLite帮助类
/// 说明:使用SQLite很简单,只需要Nuget搜SQLite 使用第一个System.Data.SQLite安装即可
/// 使用CreateDB方法 创建一个数据库文件 传入路径即可 (注意:一个数据库文件代表一个数据库)
/// 使用前请先指定连接字符串 使用SetConnectionString()方法
/// SQLite作为本地文件数据库 具有独立运行、无服务器、零配置、支持事务、低内存、原子性等特点
/// </summary>
public class SQLiteHelper
{
#region 属性
/// <summary>
/// 连接字符串
/// </summary>
private static string connectionString = string.Empty;
#endregion 属性 #region 设置连接字符串与创建数据库文件
/// <summary>
/// 根据数据源、密码、版本号设置连接字符串。
/// </summary>
/// <param name="datasource">数据源。</param>
/// <param name="password">密码。</param>
/// <param name="version">版本号(缺省为3)。</param>
public static void SetConnectionString(string datasource, string password, int version = )
{
connectionString = string.Format("Data Source={0};Version={1};password={2}",
datasource, version, password);
} /// <summary>
/// 创建一个数据库文件。如果存在同名数据库文件,则会覆盖。
/// </summary>
/// <param name="dbName">数据库文件名。为null或空串时不创建。</param>
/// <param name="password">(可选)数据库密码,默认为空。</param>
/// <exception cref="Exception"></exception>
public static void CreateDB(string dbName)
{
if (!string.IsNullOrEmpty(dbName))
{
try
{
CreateDirectory(dbName);
SQLiteConnection.CreateFile(dbName);
}
catch (Exception ex)
{
string errormes = ex.Message;
errormes += "\r\n";
errormes += LogHelper.ToMessage(ex);
string path = string.Empty;
path += AppDomain.CurrentDomain.BaseDirectory;
path += @"Unlog\SQLiteError";
path += DateTime.Now.ToString("yyyyMMddHHmm");
path += ".txt";
LogHelper.Instance.WriteLog(path, errormes);
}
}
} #region 辅助方法
/// <summary>
/// 创建父级路径
/// </summary>
/// <param name="infoPath"></param>
private static void CreateDirectory(string infoPath)
{
DirectoryInfo directoryInfo = Directory.GetParent(infoPath);
if (!directoryInfo.Exists)
{
directoryInfo.Create();
}
}
#endregion 辅助方法
#endregion 设置连接字符串与创建数据库文件 #region 命令参数封装
// <summary>
/// 准备操作命令参数
/// </summary>
/// <param name="cmd">SQLiteCommand</param>
/// <param name="conn">SQLiteConnection</param>
/// <param name="cmdText">Sql命令文本</param>
/// <param name="data">参数数组</param>
private static void PrepareCommand(SQLiteConnection conn, SQLiteCommand cmd, string cmdText, params SQLiteParameter[] parms)
{
if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Parameters.Clear();
cmd.Connection = conn;
cmd.CommandText = cmdText;
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = ;
if (parms != null && parms.Length > )
{
foreach (SQLiteParameter parameter in parms)
{
if ((parameter.Direction == ParameterDirection.Input || parameter.Direction == ParameterDirection.InputOutput) && (parameter.Value == null))
{
parameter.Value = DBNull.Value;
}
}
cmd.Parameters.AddRange(parms);
}
} #endregion 命令参数封装 #region 数据库操作
#region 创建表
/// <summary>
/// 创建表
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
public static bool CreateTable(string sql)
{
bool rr = true;
try
{
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
{
using (SQLiteCommand command = new SQLiteCommand(connection))
{
try
{
PrepareCommand(connection, command, sql, null);
int count = command.ExecuteNonQuery();
if (count > ) rr = true;
else rr = false;
}
catch (Exception ex)
{
return false;
}
}
}
}
catch (Exception ex)
{ return false;
}
return rr;
}
#endregion 创建表 #region 增删改操作
/// <summary>
/// 对SQLite数据库执行增删改操作,返回受影响的行数。
/// </summary>
/// <param name="sql">要执行的增删改的SQL语句。</param>
/// <param name="parameters">执行增删改语句所需要的参数,参数必须以它们在SQL语句中的顺序为准。</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static int ExecuteNonQuery(string sql, params SQLiteParameter[] parameters)
{
int affectedRows = ;
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
{
using (SQLiteCommand command = new SQLiteCommand(connection))
{
try
{
PrepareCommand(connection, command, sql, parameters);
//connection.Open();
//command.CommandText = sql;
//if (parameters.Length != 0)
//{
// command.Parameters.AddRange(parameters);
//}
affectedRows = command.ExecuteNonQuery();
}
catch (Exception) { throw; }
}
}
return affectedRows;
}
#endregion 增删改操作 #region 批量操作
/// <summary>
/// 批量处理数据操作语句。
/// </summary>
/// <param name="list">SQL语句集合。</param>
/// <exception cref="Exception"></exception>
public static void ExecuteNonQueryBatch(List<KeyValuePair<string, SQLiteParameter[]>> list)
{
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
try { conn.Open(); }
catch { throw; }
using (SQLiteTransaction tran = conn.BeginTransaction())
{
using (SQLiteCommand cmd = new SQLiteCommand(conn))
{
try
{
foreach (var item in list)
{
PrepareCommand(conn, cmd, item.Key, item.Value);
//cmd.CommandText = item.Key;
//if (item.Value != null)
//{
// cmd.Parameters.AddRange(item.Value);
//}
cmd.ExecuteNonQuery();
}
tran.Commit();
}
catch (Exception) { tran.Rollback(); throw; }
}
}
}
}
#endregion 批量操作 #region 查询 返回第一个
/// <summary>
/// 执行查询语句,并返回第一个结果。
/// </summary>
/// <param name="sql">查询语句。</param>
/// <returns>查询结果。</returns>
/// <exception cref="Exception"></exception>
public static object ExecuteScalar(string sql, params SQLiteParameter[] parameters)
{
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
using (SQLiteCommand cmd = new SQLiteCommand(conn))
{
try
{
PrepareCommand(conn, cmd, sql, parameters);
//conn.Open();
//cmd.CommandText = sql;
//if (parameters.Length != 0)
//{
// cmd.Parameters.AddRange(parameters);
//}
return cmd.ExecuteScalar();
}
catch (Exception) { throw; }
}
}
}
#endregion 查询 返回第一个 #region 查询 返回DT
/// <summary>
/// 执行一个查询语句,返回一个包含查询结果的DataTable。
/// </summary>
/// <param name="sql">要执行的查询语句。</param>
/// <param name="parameters">执行SQL查询语句所需要的参数,参数必须以它们在SQL语句中的顺序为准。</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static DataTable ExecuteQuery(string sql, params SQLiteParameter[] parameters)
{
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
{
using (SQLiteCommand command = new SQLiteCommand(sql, connection))
{
PrepareCommand(connection, command, sql, parameters);
//if (parameters != null)
//{
// if (parameters.Length != 0)
// {
// command.Parameters.AddRange(parameters);
// }
//} SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
DataTable data = new DataTable();
try { adapter.Fill(data); }
catch (Exception) { throw; }
return data;
}
}
}
#endregion 查询 返回DT #region 查询 返回SQLiteDataReader
/// <summary>
/// 执行一个查询语句,返回一个关联的SQLiteDataReader实例。
/// </summary>
/// <param name="sql">要执行的查询语句。</param>
/// <param name="parameters">执行SQL查询语句所需要的参数,参数必须以它们在SQL语句中的顺序为准。</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static SQLiteDataReader ExecuteReader(string sql, params SQLiteParameter[] parameters)
{
SQLiteConnection connection = new SQLiteConnection(connectionString);
SQLiteCommand command = new SQLiteCommand(sql, connection);
try
{
PrepareCommand(connection, command, sql, parameters);
//if (parameters.Length != 0)
//{
// command.Parameters.AddRange(parameters);
//}
//connection.Open();
return command.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (Exception) { throw; }
}
#endregion 查询 返回SQLiteDataReader #region 查询数据库中的所有数据类型信息
/// <summary>
/// 查询数据库中的所有数据类型信息。
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static DataTable GetSchema()
{
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
{
try
{
connection.Open();
return connection.GetSchema("TABLES");
}
catch (Exception) { throw; }
}
} #endregion 查询数据库中的所有数据类型信息 #region 判断表是否存在
public static bool IsTableExist(string tableName)
{
bool isTableExist = true;
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
{
string sql = "SELECT name FROM sqlite_master WHERE type='table' AND name = '";
sql += tableName;
sql += "'";
using (SQLiteCommand command = new SQLiteCommand(sql, connection))
{
PrepareCommand(connection, command, sql, null);
int count = command.ExecuteNonQuery();
if (count <= ) isTableExist = false;
}
}
return isTableExist; }
#endregion 判断表是否存在 #endregion 数据库操作 #region 整理数据库
/// <summary>
/// 重新组织数据库
/// SQLite 的自带命令 VACUUM。用来重新整理整个数据库达到紧凑之用,比如把删除的彻底删掉等等
/// </summary>
public static void ResetDataBass()
{
using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
var cmd = new SQLiteCommand(); if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Parameters.Clear();
cmd.Connection = conn;
cmd.CommandText = "vacuum";
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = ;
cmd.ExecuteNonQuery();
}
}
#endregion 整理数据库
}

可视化工具

分享一个可视化工具,个人感觉非常好用:

SQLiteStudio :http://sqlitestudio.pl/

问题

在项目中使用,不可能是直接在客户端的项目中直接写ADO那套,一般都会封装SQLite调用层,在调用层中添加相关的引用,这样就会有一个问题,客户端项目直接调用,会报一个错误:

解决方法为:
在客户端项目中添加两个文件夹,内部添加SQLite.Interop.dll(从SQLite调用层的Debug中拷贝)

然后,右键两个dll,选择属性,更改输出目录为始终复制。

问题解决。

总结

SQLite在本地存储方面使用非常广泛,不得不说真的很好用。

SQLite使用笔记的更多相关文章

  1. SQLite学习笔记(七)&&事务处理

    说到事务一定会提到ACID,所谓事务的原子性,一致性,隔离性和持久性.对于一个数据库而言,通常通过并发控制和故障恢复手段来保证事务在正常和异常情况下的ACID特性.sqlite也不例外,虽然简单,依然 ...

  2. Sqlite学习笔记(四)&&SQLite-WAL原理

    Sqlite学习笔记(三)&&WAL性能测试中列出了几种典型场景下WAL的性能数据,了解到WAL确实有性能优势,这篇文章将会详细分析WAL的原理,做到知其然,更要知其所以然. WAL是 ...

  3. Sqlite学习笔记(四)&&SQLite-WAL原理(转)

    Sqlite学习笔记(三)&&WAL性能测试中列出了几种典型场景下WAL的性能数据,了解到WAL确实有性能优势,这篇文章将会详细分析WAL的原理,做到知其然,更要知其所以然. WAL是 ...

  4. SQLite 学习笔记

    SQLite 学习笔记. 一.SQLite 安装    访问http://www.sqlite.org/download.html下载对应的文件.    1.在 Windows 上安装 SQLite. ...

  5. sqlite学习笔记7:C语言中使用sqlite之打开数据库

    数据库的基本内容前面都已经说得差点儿相同了.接下看看如何在C语言中使用sqlite. 一 接口 sqlite3_open(const char *filename, sqlite3 **ppDb) 打 ...

  6. Sqlite学习笔记(一)&&编译安装

    Sqlite简介 sqlite是一个开源的嵌入式文件数据库,sqlite以动态链接库的方式供应用程序调用,所有的数据库对象都存储在同一个文件中. sqlite动态库非常小,最新的3.8.11版本也只有 ...

  7. SQLite:自学笔记(1)——快速入门

    SQLite的安装和入门 了解 啥是SQLite? SQLite是一种轻巧迷你的关系型数据库管理系统.它的特点如下: 不需要一个单独的服务器进程或操作的系统(无服务器的). SQLite 不需要配置, ...

  8. SQLite学习笔记(十)&&加密

    随着移动互联网的发展,手机使用越来越广泛,sqlite作为手机端存储的一种解决方案,使用也非常普遍.但是sqlite本身安全特性却比较弱,比如不支持用户权限,只要能获取到数据库文件就能进行访问:另外也 ...

  9. SQLite学习笔记(十二)&&虚拟机指令

    上篇文章简单讨论了虚拟机的原理,这篇文章我们详细讨论下指令,具体从几种典型的SQL语句来看看每种SQL对应的指令流,以及每个指令的含义.通过explain语句,可以看到语句对应的指令流:通过pragm ...

  10. SQLite学习笔记(十一)&&虚拟机原理

    前言      我们知道任何一种关系型数据库管理系统都支持SQL(Structured Query Language),相对于文件管理系统,用户不用关心数据在数据库内部如何存取,也不需要知道底层的存储 ...

随机推荐

  1. Flask-Migrate

    终于到了Flask-Migrate,之前在看Flask-SQLAlchemy的时候, Flask支持 makemigration / migrate 吗? 答案在这里该诉你,如果你同时拥有两个三方组件 ...

  2. 微信小程序数组对象

    xml:<block wx:for="{{post_key}}" wx:for-item="{{item}}"></block> dat ...

  3. MySQL相关问题题

    1.truncate.delete.drop的区别 (1)truncate.drop是不可以rollback的,但是delete是可以rollback的.DELETE语句执行删除的过程是每次从表中删除 ...

  4. python3 error 机器学习 错误

    AttributeError: 'NoneType' object has no attribute 'sqrt' 这个错误其实是因为 plt.scatter(x[:,0],x[:,1],x[:,2] ...

  5. SSM项目思路整合NEW2

    上接于 https://www.cnblogs.com/shijinglu2018/p/10374541.html ...... 三)客户管理模块开发 说明:其实大致思路差不太多,都是首先根据前端页面 ...

  6. kubernets 概念

    理解 Kubernetes 对象 各种资源对象的理解和定义 Kubernetes 中 Pod 的选举过程

  7. Nodejs“实现”Dubbo Provider

    背景 目前nodejs应用越来越广泛,但和java的dubbo体系接入困难,所以我们需要实现node端的dubbo provider逻辑.java的dubbo provider是和consumer在一 ...

  8. python数据类型:字典dict常用操作

    字典是Python语言中的映射类型,他是以{}括起来,里面的内容是以键值对的形式储存的: Key: 不可变(可哈希)的数据类型.并且键是唯一的,不重复的. Value:任意数据(int,str,boo ...

  9. word模板导出的几种方式:第一种:占位符替换模板导出(只适用于word中含有表格形式的)

    1.占位符替换模板导出(只适用于word中含有表格形式的): /// <summary> /// 使用替换模板进行到处word文件 /// </summary> public ...

  10. [524.A]2019-05-02(星期四)登顶梧桐山邀请

    *** 看房活动召集 ***五一期间天气炎热, 除了登山活动, 还将组织看房活动.拥有一套自己的住房是很多深圳人的梦想.政府十三五期间计划供应人才住房和保障性住房35万套, 与需求相比仍很少, 排队的 ...