【原创】System.Data.SQLite内存数据库模式
对于很多嵌入式数据库来说都有对于的内存数据库模式,SQLite也不例外。内存数据库常常用于极速、实时的场景,一个很好的应用的场景是富客户端的缓存数据,一般富客户端的缓存常常需要分为落地和非落地两种,而反应到SQLite上就是主要两种模式,一种是文件类型的数据库,一种是内存模式的。而我们常常需要做的是系统启动初从文件数据库加载到内存数据库,然后在系统退出或定时的将内存数据回写到文件数据库。这种导入和导出操作,在C#版本的SQLite库中已经原生进行了支持。而C版本中实际上对应了三个函数,你可以参照SQLite Online Backup API 。
其实本人在查找SQLite的内存模式和文件模式相互备份资料的时候,发现关于使用System.Data.SQLite.dll来进行两种模式相互备份的例子比较少,而且在国内的许多网站上找不到可以直接复用的代码,即时找到了也总是夹杂着很多C版本的实现,总是让人有些摸不着头脑。虽然如此,功夫不负有心人,在stackoverflow上找到了自己想要的代码,通过反编译看System.Data.SQLite.dll看SQLiteConnection中有一个方法BackupDatabase(......),通过它可以实现数据库间的备份。
BackupDatabase(......)方法的反编译的源码如下:
// The method in System.Data.SQLite.SQLiteConnection
public void BackupDatabase(SQLiteConnection destination, string destinationName, string sourceName, int pages, SQLiteBackupCallback callback, int retryMilliseconds)
{
//省略参数检查和连接状态检查代码
//
SQLiteBase sql = this._sql;
if (sql == null)
{
throw new InvalidOperationException("Connection object has an invalid handle.");
}
SQLiteBackup sQLiteBackup = null;
try
{
sQLiteBackup = sql.InitializeBackup(destination, destinationName, sourceName);
bool flag;
while (sql.StepBackup(sQLiteBackup, pages, out flag) && (callback == null || callback(this, sourceName, destination, destinationName, pages, sql.RemainingBackup(sQLiteBackup), sql.PageCountBackup(sQLiteBackup), flag)))
{
if (flag && retryMilliseconds >= 0)
{
Thread.Sleep(retryMilliseconds);
}
if (pages == 0)
{
break;
}
}
}
catch (Exception ex)
{
if ((this._flags & SQLiteConnectionFlags.LogBackup) == SQLiteConnectionFlags.LogBackup)
{
SQLiteLog.LogMessage(0, string.Format(CultureInfo.CurrentCulture, "Caught exception while backing up database: {0}", new object[]
{
ex
}));
}
throw;
}
finally
{
if (sQLiteBackup != null)
{
sql.FinishBackup(sQLiteBackup);
}
}
}
从上面这段代码我们可以简单的看出,实际上备份还是通过InitializeBackup,StepBackup,FinishBackup这三个方法来实现。这三个方法分别对应的本地方法是sqlite3_backup_init,sqlite3_backup_step,sqlite3_backup_finish;关于这个三个方法的说明可以参考SQLite Online Backup API 。
接下来,将直接贴代码来展示如何在C#中使用System.Data.SQLite.dll来进行SQLite文件数据库与内存数据库相互备份。
//
// 软件版权: http://xiexiuli.cnblogs.com/
// 作者: xiexiuli
// 创建时间: 2014-01-20
// 功能说明: SQLite内存数据库模式的管理器
// 修改历史:
//
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.IO;
namespace LongThinking.Data
{
/// <summary>
/// SQLite内存数据库模式的处理器
/// </summary>
public class SQLiteMemoryManager : IDisposable
{
/// <summary>
/// 每个内存数据库都保持一个自己的连接
/// </summary>
private SQLiteConnection _globalConnection;
#region 构造函数
public SQLiteMemoryManager()
{
var str = "Data Source=:memory:;Version=3;New=True;";
_globalConnection = new SQLiteConnection(str);
_globalConnection.Open();
}
#endregion
#region 备份数据库
/// <summary>
/// 备份数据库
/// </summary>
/// <param name="dbFileConnectString">指定到文件数据库路径的连接串</param>
/// <param name="isFileToMemory">
/// 是否是文件数据库备份到内存数据库;
/// isFileToMemory为true指的是从文件数据库导入到当前内存数据库;
/// isFileToMemory为false指的是从当前内存数据库导出到文件数据库。
/// </param>
public void BackupDatabase(string dbFileConnectionString, bool isFileToMemory)
{
using (SQLiteConnection dbfileConnection = new SQLiteConnection(dbFileConnectionString))
{
this.BackupDatabase(dbfileConnection, isFileToMemory);
}
}
/// <summary>
/// 备份数据库
/// </summary>
/// <param name="dbPath">指定到文件数据库的文件全路径</param>
/// <param name="password">文件数据库密码</param>
/// <param name="isFileToMemory">
/// 是否是文件数据库备份到内存数据库;
/// isFileToMemory为true指的是从文件数据库导入到当前内存数据库;
/// isFileToMemory为false指的是从当前内存数据库导出到文件数据库。
/// </param>
public void BackupDatabase(string dbPath, string password, bool isFileToMemory)
{
string dbFileConnectString = "Data Source=" + dbPath + ";Pooling=true;FailIfMissing=false;Password=" + password;
using (SQLiteConnection dbfileConnection = new SQLiteConnection(dbFileConnectString))
{
this.BackupDatabase(dbfileConnection, isFileToMemory);
}
}
/// <summary>
/// 备份数据库
/// </summary>
/// <param name="dbfileConnection">文件数据库的连接,该连接状态需要是打开的或者是未打开过;关闭状态的连接,默认会帮你打开</param>
/// <param name="isFileToMemory">
/// 是否是文件数据库备份到内存数据库;
/// isFileToMemory为true指的是从文件数据库导入到当前内存数据库;
/// isFileToMemory为false指的是从当前内存数据库导出到文件数据库。
/// </param>
public void BackupDatabase(SQLiteConnection dbfileConnection, bool isFileToMemory)
{
//如果连接是关闭状态就打开
if (dbfileConnection.State == ConnectionState.Closed)
{
dbfileConnection.Open();
}
if (isFileToMemory)
{
dbfileConnection.BackupDatabase(_globalConnection, "main", "main", -1, null, 0);
}
else
{
_globalConnection.BackupDatabase(dbfileConnection, "main", "main", -1, null, 0);
}
}
#endregion
#region 销毁
~SQLiteMemoryManager()
{
this.Dispose(true);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
if (_globalConnection != null)
{
_globalConnection.Dispose();
}
}
}
#endregion
}
}
上面的代码我已经删除很多数据操作的方法,等我测试完那些操作方法将提供完整版的类和工程供大家下载。
参考:
http://www.sqlite.org/backup.html
http://stackoverflow.com/questions/17298988/system-data-sqlite-backupdatabase-throws-not-an-error
【原创】System.Data.SQLite内存数据库模式的更多相关文章
- 启用SQLite的Data Provider 运行WECOMPANYSITE时遇到ERROR CREATING CONTEXT 'SPRING.ROOT': ERROR THROWN BY A DEPENDENCY OF OBJECT 'SYSTEM.DATA.SQLITE'
从网上下载的源码WeCompanySite,运行时报错 Error creating context 'spring.root': Error thrown by a dependency of ob ...
- .Net4.0以上使用System.Data.Sqlite
最近对Sqlite感兴趣,就尝试了一下用c#连接,我用的版本是vs2013,默认开发环境是.net4.5,,按照网上的教材,下载了System.Data.Sqlite,然后写了下面这个简单的测试代码, ...
- IIS发布网站出现“未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项。”的解决方法
未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项.试图加载格式不正确的程序. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈 ...
- 引用64位dll时候出现 未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项。试图加载格式不正确的程序。
引用64位dll时候出现 未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项.试图加载格式不正确的程序. 需要在web.config增加配置 <startup use ...
- Could not load file or assembly 'System.Data.SQLite' or one of its dependencies
试图加载格式不正确的程 异常类型 异常消息Could not load file or assembly 'System.Data.SQLite' or one of its dependencies ...
- System.Data.SQLite
SQLite介绍 在介绍System.Data.SQLite之前需要介绍一下SQLite,SQLite是一个类似于Access的单机版数据库管理系统,它将所有数据库的定义(包括定义.表.索引和数据本身 ...
- 未能加载文件或程序集“System.Data.SQLite.DLL”或它的某一个依赖项
今天在部署code到测试环境的时候 出现了未能加载文件或程序集"System.Data.SQLite.DLL"或它的某一个依赖项 这个错误,其实错误的的原因有很多,1.典型的是是版 ...
- SQLite 解决:Could not load file or assembly 'System.Data.SQLite ... 试图加载格式不正确的程序/or one of its dependencies. 找不到指定的模块。
Could not load file or assembly 'System.Data.SQLite.dll' or one of its dependencies. 找不到指定的模块. 错误提示 ...
- 能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项。试图加载格式不正确的程序。
现象: 能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项.试图加载格式不正确的程序.
随机推荐
- 移动前端开发之 viewport 的深入理解
移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有关的meta标签的使用,才能更好地让我们的网页适配或响 ...
- NFinal 视图—用户控件
自定义控件 定义控件 以Label控件为例: 1.首先在Common文件夹下添加Label.cs文件,其中代码如下: //a.control的实体类必须继承NFinal.UserControl类 pu ...
- servlet乱码以及解决
// 浏览器提交的数据是000110011(码表中对应的<编码> )等东西. // 浏览器以什么<码表>打开浏览器(而空中浏览器使用的编码是:<meta http-eq ...
- Know Thy Complexities!
http://bigocheatsheet.com/ Hi there! This webpage covers the space and time Big-O complexities of c ...
- PureLayout(轻量级自动布局)
直接整理用法 1.设置高度宽度 [view1 autoSetDimension:ALDimensionHeight toSize:70.0]; [view1 autoSetDimension:ALDi ...
- 南阳oj-喷水装置(一)
喷水装置(一) 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以 ...
- information_schema.collations 学习
information_schema.collations 表中的每一行对应一个排序规则 1.information_schema.collations 表中学用列: 1.id :排序规则的ID 2. ...
- Bitmap 与ImageSource之间的转换
public class ImageConverter { [DllImport("gdi32.dll", SetLastError = true)] private static ...
- [转载] 50个Android开发人员必备UI效果源码
好东西,多学习! Android 仿微信之主页面实现篇Android 仿微信之界面导航篇Android 高仿QQ 好友分组列表Android 高仿QQ 界面滑动效果Android 高仿QQ 登陆界面A ...
- USB class总结
以下是总结的USB的类,不同的USB类,主机询问的描述符格式和内容都不一样,具体的descriptor的内容可以查看 USB spec(http://www.usb.org/home/),如HID的s ...