Context
Backup
API Support
SQLite.net provides an API method on a SQLiteConnection object to perform the SQLite backup operation.In order to call this method you need to pass the following parameters:
- destination - An open SQLiteConnection for the destination database;
- destinationName - "main" to backup to the main database file, "temp" to backup to the temporary database file, or the name specified after the AS keyword in an ATTACH statement for an attached database;
- sourceName - "main" to backup from the main database file, "temp" to backup from the temporary database file, or the name specified after the AS keyword in an ATTACH statement for an attached database;
- pages - the number of pages on disk to back up with every iteration of the algorithm, -1 will backup the whole database in one iteration;
- callback - a function that is called between every iteration, returns true to continue, or false to stop the algorithm;
- retryMilliseconds - number of milliseconds to wait before retrying a failed iteration of the algorithm.
Extending with IObservable<T> and IObserver<T>
The following class wraps the iterative algorithm within an IObservable<SqliteBackupEvent> object. The SqliteBackupEvent class just contains the properties returned to the callback:1: public class SqliteBackup : IObservable<SqliteBackupEvent>
2: {
3: private readonly List<IObserver<SqliteBackupEvent>> _observers;
4:
5: public SqliteBackup()
6: {
7: _observers = new List<IObserver<SqliteBackupEvent>>();
8: }
9:
10: public void Execute(string sourceConnectionString, string destinationConnectionString, int pagesToBackupInEachStep)
11: {
12: try
13: {
14: using (var srcConnection = new SQLiteConnection(sourceConnectionString))
15: using (var destConnection = new SQLiteConnection(destinationConnectionString))
16: {
17: srcConnection.Open();
18: destConnection.Open();
19:
20: // Need to use the "main" names as specified at http://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupinit
21: srcConnection.BackupDatabase(destConnection, "main", "main", pagesToBackupInEachStep, Callback, 10);
22:
23: destConnection.Close();
24: srcConnection.Close();
25: }
26: }
27: catch (Exception ex)
28: {
29: foreach (var observer in _observers)
30: observer.OnError(ex);
31: }
32:
33: foreach (var observer in _observers)
34: observer.OnCompleted();
35: }
36:
37: protected virtual bool Callback(SQLiteConnection srcConnection, string srcName, SQLiteConnection destConnection, string destName,
38: int pages, int remaining, int pageCount, bool retry)
39: {
40: var @event = new SqliteBackupEvent(pages, remaining, pageCount, retry);
41:
42: foreach (var observer in _observers)
43: observer.OnNext(@event);
44:
45: return true;
46: }
47:
48: public IDisposable Subscribe(IObserver<SqliteBackupEvent> observer)
49: {
50: if (!_observers.Contains(observer))
51: _observers.Add(observer);
52: return new Unsubscriber(_observers, observer);
53: }
54:
55: private class Unsubscriber : IDisposable
56: {
57: private readonly List<IObserver<SqliteBackupEvent>> _observers;
58: private readonly IObserver<SqliteBackupEvent> _observer;
59:
60: public Unsubscriber(List<IObserver<SqliteBackupEvent>> observers, IObserver<SqliteBackupEvent> observer)
61: {
62: this._observers = observers;
63: this._observer = observer;
64: }
65:
66: public void Dispose()
67: {
68: if (_observer != null && _observers.Contains(_observer))
69: _observers.Remove(_observer);
70: }
71: }
72: }
1: public class SqliteBackupEvent
2: {
3: public int Pages { get; private set; }
4: public int Remaining { get; private set; }
5: public int PageCount { get; private set; }
6: public bool Retry { get; private set; }
7:
8: public SqliteBackupEvent(int pages, int remaining, int pageCount, bool retry)
9: {
10: Pages = pages;
11: Remaining = remaining;
12: PageCount = pageCount;
13: Retry = retry;
14: }
15: }
1: public class ConsoleWriterObserver : IObserver<SqliteBackupEvent>
2: {
3: public void OnNext(SqliteBackupEvent value)
4: {
5: Console.WriteLine("{0} - {1} - {2} - {3}", value.Pages, value.PageCount, value.Remaining, value.Retry);
6: }
7:
8: public void OnError(Exception error)
9: {
10: Console.WriteLine(error.Message);
11: }
12:
13: public void OnCompleted()
14: {
15: Console.WriteLine("Complete");
16: }
17: }
1: const string srcConnectionString = @"Data Source="".\data.db"";Version=3;";
2: const string destConnectionString = @"Data Source="".\newdata.db"";Version=3;";
3:
4: var backup = new SqliteBackup();
5:
6: var unsubscriber = backup.Subscribe(new ConsoleWriterObserver());
7:
8: backup.Execute(srcConnectionString, destConnectionString, 50);
9:
10: unsubscriber.Dispose();
11:
12: Console.ReadLine();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
一下是根据自己的实际情况写的一个简易版的备份和还原
备份数据库:
1 public void BackUpDateBase() 2 { 3 string destDBFileName = configMng.backUpFileName; 4 int index = destDBFileName.IndexOf('.'); 5 string destDBFileNameProcess = destDBFileName.Insert(index, "_process"); 6 SQLiteConnection cnDest = new SQLiteConnection(@"Data Source=" + configMng.backUpPath + @"\" + destDBFileNameProcess); 7 SQLiteConnection cnSource = new SQLiteConnection(@"Data Source=..\DataBase\" + configMng.backUpFileName); 8 try 9 { 10 cnDest.Open(); 11 cnSource.Open(); 12 13 cnSource.BackupDatabase(cnDest, "main", "main", -1, null, 0); 14 cnDest.Close(); 15 cnSource.Close(); 16 17 if (File.Exists(configMng.backUpPath + @"\" + destDBFileNameProcess)) 18 { 19 destDBFileName = destDBFileName.Insert(index, DateTime.Now.ToString("yyyyMMddHHmmss")); 20 File.Move(configMng.backUpPath + @"\" + destDBFileNameProcess, configMng.backUpPath + @"\" + destDBFileName); 21 } 22 } 23 catch(Exception e) 24 { 25 LogHelper.WiteLog("SQLiteBackUpService backup faild!"); 26 if (cnDest.State == ConnectionState.Open) 27 { 28 cnDest.Close(); 29 } 30 if (cnSource.State == ConnectionState.Open) 31 { 32 cnSource.Close(); 33 } 34 35 } 36 37 }
红色代码部分就是用于数据库的备份的,这时SQLite提供的在线备份,好处是备份的同时不会影响数据库的使用,当然这个函数也可以用于数据库的还原,
这个函数后几个参数可以实现备份时的进度反馈,
例如下面的用法,就能反映进度:
cnSource.BackupDatabase(cnDest, "main", "main", 2, Callback, -1); protected bool Callback(SQLiteConnection srcConnection, string srcName, SQLiteConnection destConnection, string destName, int pages, int remaining, int pageCount, bool retry) { process = 100 *(pageCount - remaining) / pageCount; if (remaining <= pages) { isRestore = false; process = 100; } return true; }
上述代码中BackupDatabase()函数在备份的过程中就能回调Callback函数,他调用的频率是由第四个参数决定的,当前为2表示每备份2页就调用callback,
在callback函数中,pagecount就是当前备份的数据库的总页数,remaining就是还没备份的,pages就是前面的2(备份的频率)。