1. 程式人生 > >C# 中 SQLite 使用介紹

C# 中 SQLite 使用介紹

適用於 零配置 select pan asi 數據庫 sys variant oca

原文:C# 中 SQLite 使用介紹

關於SQLite

SQLite是一款輕型的嵌入式的遵守ACID的關系型數據庫管理系統,誕生已有15個年頭了。隨著移動互聯的發展,現在得到了更廣泛的使用。

在使用SQLite之前,我們勢必要先了解它一些“個性”的地方。下面是它的一些特點:

1、 自包含。SQLite很大層度上是獨立的,他只需要非常小的外部庫支持。任何程序能夠訪問磁盤就可以使用SQLite數據庫。這使它適用於嵌入式設備,缺乏桌面計算機支持的基礎設施。這也使得SQLite適用於不作任何修改就可運行在不同配置電腦上的程序。

2、 無服務器。大多數SQL數據庫引擎被實現為一個單獨的服務器進程。程序要訪問數據庫與服務器通信使用某種形式的進程間通信(通常是TCP / IP),向服務器發送請求並接收返回結果。SQLite則不是這種工作方式。對於SQLite,想要訪問數據庫直接從磁盤上的對數據庫文件執行讀和寫操作。沒有中間的服務器進程。

3、 零配置。使用SQLite不需要“安裝”。沒有“設置”程序。沒有服務器進程需要啟動,停止,或配置。不需要管理員來創建一個新的數據庫實例或訪問權限分配給用戶。SQLite不使用配置文件。

4、 支持事務。事務數據庫的所有更改和查詢表現出原子性、一致性、隔離性、持久性(ACID)。執行SQLite的事務操作時,要麽完全執行,要麽不執行,即使寫入磁盤的操作被程序崩潰,斷電等故障打斷。

5、 開源。和前面的特點相比,這個似乎沒有多大關系。之所以把它作為一個特點,是因為開源在很大層度上會成為我們選擇一個解決方案的重要維度。

  除了這些,SQLite還有著比同是開源的Mysql、PostgreSQL數據庫更快的處理效率,更低的資源占用。看起來很“完美”的東西背後往往也有著致命的缺陷。SQLite的缺陷雖不能說致命,但也足以讓你在選擇的過程中說NO。如果你要求更精準的控制數據庫訪問,細粒度鎖(SQLite只提供數據庫級的鎖定)以及很好的並發性(雖然可以手動實現並發,但是性能不高,也容易出現死鎖),SQLite也許不適合你。另外,SQLite也不適合遠程訪問,雖然可以通過網絡共享的方式運行,但是會存在文件鎖定的問題,而且訪問網絡共享相關的延遲會導致性能的下降。

安裝配置

前面說過了,使用SQLite是超級簡單的,無需安裝,只需要在官網下載庫文件添加引用即可。當然,還有很簡單的一些配置。還有更簡單的方法,使用Nuget添加SQLite庫文件並自動配置,這簡直是一鍵搞定啊。

首先,在Nuget中找到SQLite。這裏我們選擇第一個安裝。

技術分享圖片

  會自動安裝如下庫。

技術分享圖片

  安裝後會自動添加如下庫的引用。

技術分享圖片

  並自動添加如下配置。

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <configuration>
 3   <
configSections> 4 <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> 5 <section name="entityFramework" 6 type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 7 requirePermission="false"/> 8 </configSections> 9 10 <entityFramework> 11 <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> 12 <parameters> 13 <parameter value="v11.0"/> 14 </parameters> 15 </defaultConnectionFactory> 16 <providers> 17 <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/> 18 <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6"/> 19 </providers> 20 </entityFramework> 21 <system.data> 22 <DbProviderFactories> 23 <remove invariant="System.Data.SQLite.EF6"/><add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" 24 description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6"/></DbProviderFactories> 25 </system.data></configuration>

SQLite的使用

上面的準備工作已經就緒。接下來開始使用SQLite。這裏不對如何創建數據庫作介紹,在實際工作中,我一般會選擇使用Navicat for SQLite來創建數據庫,方便快捷。如果有編碼創建數據庫要求,自行問度娘。如果要使用Linq,別忘了添加System.Data.Linq的引用。

技術分享圖片
  1     /// <summary>
  2     /// SQLite數據庫幫助類
  3     /// </summary>
  4     public class SQLiteHelper
  5     {
  6         /// <summary>
  7         /// 數據庫路徑
  8         /// </summary>
  9         private static readonly string m_DataSource = ConfigurationManager.AppSettings["Test"];
 10 
 11         /// <summary>
 12         /// ConnectionString樣例:Data Source=Test.db;Pooling=true;FailIfMissing=false
 13         /// </summary>
 14         private static readonly string m_ConnectionString;
 15 
 16         /// <summary>
 17         /// 靜態構造函數,初始化連接字符串,檢查數據庫連接
 18         /// </summary>
 19         static SQLiteHelper()
 20         {
 21             try
 22             {
 23                 SQLiteConnectionStringBuilder connectionStringBuilder = new SQLiteConnectionStringBuilder
 24                 {
 25                     Version = 3,
 26                     Pooling = true,
 27                     FailIfMissing = false,
 28                     DataSource = m_DataSource
 29                 };
 30                 m_ConnectionString = connectionStringBuilder.ConnectionString;
 31                 using (SQLiteConnection conn = new SQLiteConnection(m_ConnectionString))
 32                 {
 33                     conn.Open();
 34                 }
 35             }
 36             catch { }
 37         }
 38 
 39         #region basic method
 40 
 41         /// <summary>
 42         /// 獲得連接對象
 43         /// </summary>
 44         /// <returns></returns>
 45         private static SQLiteConnection GetSQLiteConnection()
 46         {
 47             return new SQLiteConnection(m_ConnectionString);
 48         }
 49 
 50         /// <summary>
 51         /// 預備命令
 52         /// </summary>
 53         /// <param name="cmd"></param>
 54         /// <param name="conn"></param>
 55         /// <param name="cmdText"></param>
 56         /// <param name="commandParameters"></param>
 57         private static void PrepareCommand(SQLiteCommand cmd, SQLiteConnection conn, string cmdText, params object[] commandParameters)
 58         {
 59             if (conn.State != ConnectionState.Open)
 60                 conn.Open();
 61             cmd.Parameters.Clear();
 62             cmd.Connection = conn;
 63             cmd.CommandText = cmdText;
 64             cmd.CommandType = CommandType.Text;
 65             cmd.CommandTimeout = 30;
 66             if (commandParameters != null)
 67             {
 68                 foreach (object parm in commandParameters)
 69                     cmd.Parameters.AddWithValue(string.Empty, parm);
 70 
 71                 //for (int i = 0; i < p.Length; i++)
 72                 //    cmd.Parameters[i].Value = p[i];
 73             }
 74         }
 75 
 76         /// <summary>
 77         /// 返回受影響的行數
 78         /// </summary>
 79         /// <param name="cmdText">執行語句</param>
 80         /// <param name="commandParameters">傳入的參數</param>
 81         /// <returns>返回受影響行數</returns>
 82         public static int ExecuteNonQuery(string cmdText, params object[] commandParameters)
 83         {
 84             SQLiteCommand command = new SQLiteCommand();
 85             using (SQLiteConnection connection = GetSQLiteConnection())
 86             {
 87                 PrepareCommand(command, connection, cmdText, commandParameters);
 88                 return command.ExecuteNonQuery();
 89             }
 90         }
 91 
 92         /// <summary>
 93         /// 返回表集合
 94         /// </summary>
 95         /// <param name="cmdText">執行語句</param>
 96         /// <param name="commandParameters">傳入的參數</param>
 97         /// <returns>返回DataSet</returns>
 98         public static DataSet ExecuteDataset(string cmdText, params object[] commandParameters)
 99         {
100             DataSet ds = new DataSet();
101             SQLiteCommand command = new SQLiteCommand();
102             using (SQLiteConnection connection = GetSQLiteConnection())
103             {
104                 PrepareCommand(command, connection, cmdText, commandParameters);
105                 SQLiteDataAdapter da = new SQLiteDataAdapter(command);
106                 da.Fill(ds);
107             }
108             return ds;
109         }
110 
111         /// <summary>
112         /// 返回SqlDataReader對象
113         /// </summary>
114         /// <param name="cmdText">執行語句</param>
115         /// <param name="commandParameters">傳入的參數</param>
116         /// <returns>返回SQLiteDataReader</returns>
117         public static SQLiteDataReader ExecuteReader(string cmdText, params object[] commandParameters)
118         {
119             SQLiteCommand command = new SQLiteCommand();
120             SQLiteConnection connection = GetSQLiteConnection();
121             try
122             {
123                 PrepareCommand(command, connection, cmdText, commandParameters);
124                 SQLiteDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
125                 return reader;
126             }
127             catch
128             {
129                 connection.Close();
130                 throw;
131             }
132         }
133 
134         /// <summary>
135         /// 返回表第一行
136         /// </summary>
137         /// <param name="cmdText">執行語句</param>
138         /// <param name="commandParameters">傳入的參數</param>
139         /// <returns>返回:第一行</returns>
140         public static DataRow ExecuteDataRow(string cmdText, params object[] commandParameters)
141         {
142             DataSet ds = ExecuteDataset(cmdText, commandParameters);
143             if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
144                 return ds.Tables[0].Rows[0];
145             return null;
146         }
147 
148         /// <summary>
149         /// 返回結果集中的第一行第一列,忽略其他行或列
150         /// </summary>
151         /// <param name="cmdText">執行語句</param>
152         /// <param name="commandParameters">傳入的參數</param>
153         /// <returns>返回:第一行第一列</returns>
154         public static object ExecuteScalar(string cmdText, params object[] commandParameters)
155         {
156             SQLiteCommand cmd = new SQLiteCommand();
157             using (SQLiteConnection connection = GetSQLiteConnection())
158             {
159                 PrepareCommand(cmd, connection, cmdText, commandParameters);
160                 return cmd.ExecuteScalar();
161             }
162         }
163 
164         #endregion
165 
166 
167         #region advanced method
168 
169         /// <summary>
170         /// 獲取表所有數據
171         /// </summary>
172         /// <typeparam name="T">實體類型</typeparam>
173         /// <param name="tableName">表名</param>
174         /// <returns>表所有數據</returns>
175         public static List<T> GetTableData<T>(string tableName) where T : class
176         {
177             List<T> dataList = new List<T>();
178             try
179             {
180                 using (SqliteDataContext context = new SqliteDataContext(new SQLiteConnection(m_ConnectionString)))
181                 {
182                     string sql = "select * from " + tableName;
183                     dataList = context.ExecuteQuery<T>(sql).ToList();
184                     context.SubmitChanges();
185                 }
186             }
187             catch { }
188             return dataList;
189         }
190 
191         /// <summary>
192         /// 獲取表數據
193         /// </summary>
194         /// <typeparam name="T">實體類型</typeparam>
195         /// <param name="cmdText">sql語句</param>
196         /// <param name="parameter">參數</param>
197         /// <returns>表所有數據</returns>
198         public static List<T> GetTableData<T>(string cmdText, params object[] parameter) where T : class
199         {
200             List<T> dataList = new List<T>();
201             try
202             {
203                 using (SqliteDataContext context = new SqliteDataContext(new SQLiteConnection(m_ConnectionString)))
204                 {
205                     dataList = context.ExecuteQuery<T>(cmdText, parameter).ToList();
206                 }
207             }
208             catch {}
209             return dataList;
210         }
211 
212         /// <summary>
213         /// 插入表數據
214         /// </summary>
215         /// <typeparam name="T">數據類型</typeparam>
216         /// <param name="tableName">表名</param>
217         /// <param name="dataList">數據集合</param>
218         /// <returns>true或false</returns>
219         public static bool BatchInsert<T>(string tableName, List<T> dataList)
220         {
221             try
222             {
223                 if (dataList != null && dataList.Count > 0)
224                 {
225                     var temp = dataList[0];
226                     PropertyInfo[] propertyInfos = temp.GetType().GetProperties();
227                     List<string> propertyStrs = new List<string>();
228                     string propertyStr = "";
229                     foreach (var propertyInfo in propertyInfos)
230                     {
231                         propertyStrs.Add(propertyInfo.Name);
232                         propertyStr = propertyStr + "@" + propertyInfo.Name + ",";
233                     }
234                     propertyStr = propertyStr.Remove(propertyStr.Length - 1);
235 
236                     using (SQLiteConnection conn = new SQLiteConnection(m_ConnectionString))
237                     {
238                         using (SQLiteCommand command = new SQLiteCommand(conn))
239                         {
240                             command.Connection.Open();
241                             using (SQLiteTransaction transaction = conn.BeginTransaction())
242                             {
243                                 command.Transaction = transaction;
244                                 command.CommandText = "insert into " + tableName + " values(" + propertyStr + ")";
245                                 foreach (var needInsertData in dataList)
246                                 {
247                                     command.Parameters.Clear();
248                                     for (int i = 0; i < propertyStrs.Count; i++)
249                                     {
250                                         command.Parameters.AddWithValue("@" + propertyStrs[i], propertyInfos[i].GetValue(needInsertData, null));
251                                     }
252                                     command.ExecuteNonQuery();
253                                 }
254                                 transaction.Commit();
255                             }
256                         }
257                     }
258                 }
259             }
260             catch (Exception ex)
261             {
262                 return false;
263             }
264             return true;
265         }
266 
267         /// <summary>
268         /// 刪除表數據
269         /// </summary>
270         /// <param name="tableName">表名</param>
271         /// <returns>true或false</returns>
272         public static bool DeleteTableData(string tableName)
273         {
274             try
275             {
276                 using (SQLiteConnection conn = new SQLiteConnection(m_ConnectionString))
277                 {
278                     using (SQLiteCommand command = new SQLiteCommand(conn))
279                     {
280                         command.Connection.Open();
281                         command.CommandText = "delete from " + tableName;
282                         command.ExecuteNonQuery();
283                     }
284                 }
285             }
286             catch (Exception ex)
287             {
288                 return false;
289             }
290             return true;
291         }
292 
293         #endregion
294     }
SQLiteHelper

技術分享圖片
 1     /// <summary>
 2     /// Linq to SQLite
 3     /// </summary>
 4     public class SQLiteDataContext : DataContext
 5     {
 6         public SQLiteDataContext(string connection, MappingSource mappingSource) :
 7             base(connection, mappingSource)
 8         {
 9         }
10         public SQLiteDataContext(IDbConnection connection, MappingSource mappingSource) :
11             base(connection, mappingSource)
12         {
13         }
14         public SQLiteDataContext(string connectionString) :
15             base(new SQLiteConnection(connectionString))
16         {
17         }
18         public SQLiteDataContext(IDbConnection connection) :
19             base(connection)
20         {
21         }
22     }
SQLiteDataContext

  如果看了上面的Code,會發現查詢表數據方法是使用的Linq。這種方式相比遍歷IDataReader要高效得多。只是目前.NET只支持查詢,如果想要實現增刪改需要第三方庫支持。常見的有Dblinq 、linqconnect、linq2db和ado.net sqlite data provider等。不過使用事務批量插入數據也非常的快。

寫在後面

  SQLite作為一款輕型高效的嵌入式數據庫,適合簡單高性能低並發的應用,在移動端使用將會是廣泛的,如果是高通信量的Web站點,SQLite是不合適的。

  據@InkFx指出,也看了一些大數據案例,證實SQLite對高負載支持也很好(未親自測試)。當然,這種高負載也會受制於運行時的文件系統。

  

擴展閱讀:

http://blchen.com/sqlite-data-provider-in-visual-studio-2012/

C# 中 SQLite 使用介紹