关于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。这里我们选择第一个安装。

  会自动安装如下库。

  安装后会自动添加如下库的引用。

  并自动添加如下配置。

 <?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false"/>
</configSections> <entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0"/>
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6"/>
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite.EF6"/><add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6"
description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6"/></DbProviderFactories>
</system.data></configuration>

SQLite的使用

上面的准备工作已经就绪。接下来开始使用SQLite。这里不对如何创建数据库作介绍,在实际工作中,我一般会选择使用Navicat for SQLite来创建数据库,方便快捷。如果有编码创建数据库要求,自行问度娘。如果要使用Linq,别忘了添加System.Data.Linq的引用。

     /// <summary>
/// SQLite数据库帮助类
/// </summary>
public class SQLiteHelper
{
/// <summary>
/// 数据库路径
/// </summary>
private static readonly string m_DataSource = ConfigurationManager.AppSettings["Test"]; /// <summary>
/// ConnectionString样例:Data Source=Test.db;Pooling=true;FailIfMissing=false
/// </summary>
private static readonly string m_ConnectionString; /// <summary>
/// 静态构造函数,初始化连接字符串,检查数据库连接
/// </summary>
static SQLiteHelper()
{
try
{
SQLiteConnectionStringBuilder connectionStringBuilder = new SQLiteConnectionStringBuilder
{
Version = ,
Pooling = true,
FailIfMissing = false,
DataSource = m_DataSource
};
m_ConnectionString = connectionStringBuilder.ConnectionString;
using (SQLiteConnection conn = new SQLiteConnection(m_ConnectionString))
{
conn.Open();
}
}
catch { }
} #region basic method /// <summary>
/// 获得连接对象
/// </summary>
/// <returns></returns>
private static SQLiteConnection GetSQLiteConnection()
{
return new SQLiteConnection(m_ConnectionString);
} /// <summary>
/// 预备命令
/// </summary>
/// <param name="cmd"></param>
/// <param name="conn"></param>
/// <param name="cmdText"></param>
/// <param name="commandParameters"></param>
private static void PrepareCommand(SQLiteCommand cmd, SQLiteConnection conn, string cmdText, params object[] commandParameters)
{
if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Parameters.Clear();
cmd.Connection = conn;
cmd.CommandText = cmdText;
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = ;
if (commandParameters != null)
{
foreach (object parm in commandParameters)
cmd.Parameters.AddWithValue(string.Empty, parm); //for (int i = 0; i < p.Length; i++)
// cmd.Parameters[i].Value = p[i];
}
} /// <summary>
/// 返回受影响的行数
/// </summary>
/// <param name="cmdText">执行语句</param>
/// <param name="commandParameters">传入的参数</param>
/// <returns>返回受影响行数</returns>
public static int ExecuteNonQuery(string cmdText, params object[] commandParameters)
{
SQLiteCommand command = new SQLiteCommand();
using (SQLiteConnection connection = GetSQLiteConnection())
{
PrepareCommand(command, connection, cmdText, commandParameters);
return command.ExecuteNonQuery();
}
} /// <summary>
/// 返回表集合
/// </summary>
/// <param name="cmdText">执行语句</param>
/// <param name="commandParameters">传入的参数</param>
/// <returns>返回DataSet</returns>
public static DataSet ExecuteDataset(string cmdText, params object[] commandParameters)
{
DataSet ds = new DataSet();
SQLiteCommand command = new SQLiteCommand();
using (SQLiteConnection connection = GetSQLiteConnection())
{
PrepareCommand(command, connection, cmdText, commandParameters);
SQLiteDataAdapter da = new SQLiteDataAdapter(command);
da.Fill(ds);
}
return ds;
} /// <summary>
/// 返回SqlDataReader对象
/// </summary>
/// <param name="cmdText">执行语句</param>
/// <param name="commandParameters">传入的参数</param>
/// <returns>返回SQLiteDataReader</returns>
public static SQLiteDataReader ExecuteReader(string cmdText, params object[] commandParameters)
{
SQLiteCommand command = new SQLiteCommand();
SQLiteConnection connection = GetSQLiteConnection();
try
{
PrepareCommand(command, connection, cmdText, commandParameters);
SQLiteDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
return reader;
}
catch
{
connection.Close();
throw;
}
} /// <summary>
/// 返回表第一行
/// </summary>
/// <param name="cmdText">执行语句</param>
/// <param name="commandParameters">传入的参数</param>
/// <returns>返回:第一行</returns>
public static DataRow ExecuteDataRow(string cmdText, params object[] commandParameters)
{
DataSet ds = ExecuteDataset(cmdText, commandParameters);
if (ds != null && ds.Tables.Count > && ds.Tables[].Rows.Count > )
return ds.Tables[].Rows[];
return null;
} /// <summary>
/// 返回结果集中的第一行第一列,忽略其他行或列
/// </summary>
/// <param name="cmdText">执行语句</param>
/// <param name="commandParameters">传入的参数</param>
/// <returns>返回:第一行第一列</returns>
public static object ExecuteScalar(string cmdText, params object[] commandParameters)
{
SQLiteCommand cmd = new SQLiteCommand();
using (SQLiteConnection connection = GetSQLiteConnection())
{
PrepareCommand(cmd, connection, cmdText, commandParameters);
return cmd.ExecuteScalar();
}
} #endregion #region advanced method /// <summary>
/// 获取表所有数据
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="tableName">表名</param>
/// <returns>表所有数据</returns>
public static List<T> GetTableData<T>(string tableName) where T : class
{
List<T> dataList = new List<T>();
try
{
using (SqliteDataContext context = new SqliteDataContext(new SQLiteConnection(m_ConnectionString)))
{
string sql = "select * from " + tableName;
dataList = context.ExecuteQuery<T>(sql).ToList();
context.SubmitChanges();
}
}
catch { }
return dataList;
} /// <summary>
/// 获取表数据
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
/// <param name="cmdText">sql语句</param>
/// <param name="parameter">参数</param>
/// <returns>表所有数据</returns>
public static List<T> GetTableData<T>(string cmdText, params object[] parameter) where T : class
{
List<T> dataList = new List<T>();
try
{
using (SqliteDataContext context = new SqliteDataContext(new SQLiteConnection(m_ConnectionString)))
{
dataList = context.ExecuteQuery<T>(cmdText, parameter).ToList();
}
}
catch {}
return dataList;
} /// <summary>
/// 插入表数据
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
/// <param name="tableName">表名</param>
/// <param name="dataList">数据集合</param>
/// <returns>true或false</returns>
public static bool BatchInsert<T>(string tableName, List<T> dataList)
{
try
{
if (dataList != null && dataList.Count > )
{
var temp = dataList[];
PropertyInfo[] propertyInfos = temp.GetType().GetProperties();
List<string> propertyStrs = new List<string>();
string propertyStr = "";
foreach (var propertyInfo in propertyInfos)
{
propertyStrs.Add(propertyInfo.Name);
propertyStr = propertyStr + "@" + propertyInfo.Name + ",";
}
propertyStr = propertyStr.Remove(propertyStr.Length - ); using (SQLiteConnection conn = new SQLiteConnection(m_ConnectionString))
{
using (SQLiteCommand command = new SQLiteCommand(conn))
{
command.Connection.Open();
using (SQLiteTransaction transaction = conn.BeginTransaction())
{
command.Transaction = transaction;
command.CommandText = "insert into " + tableName + " values(" + propertyStr + ")";
foreach (var needInsertData in dataList)
{
command.Parameters.Clear();
for (int i = ; i < propertyStrs.Count; i++)
{
command.Parameters.AddWithValue("@" + propertyStrs[i], propertyInfos[i].GetValue(needInsertData, null));
}
command.ExecuteNonQuery();
}
transaction.Commit();
}
}
}
}
}
catch (Exception ex)
{
return false;
}
return true;
} /// <summary>
/// 删除表数据
/// </summary>
/// <param name="tableName">表名</param>
/// <returns>true或false</returns>
public static bool DeleteTableData(string tableName)
{
try
{
using (SQLiteConnection conn = new SQLiteConnection(m_ConnectionString))
{
using (SQLiteCommand command = new SQLiteCommand(conn))
{
command.Connection.Open();
command.CommandText = "delete from " + tableName;
command.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
return false;
}
return true;
} #endregion
}

SQLiteHelper

     /// <summary>
/// Linq to SQLite
/// </summary>
public class SQLiteDataContext : DataContext
{
public SQLiteDataContext(string connection, MappingSource mappingSource) :
base(connection, mappingSource)
{
}
public SQLiteDataContext(IDbConnection connection, MappingSource mappingSource) :
base(connection, mappingSource)
{
}
public SQLiteDataContext(string connectionString) :
base(new SQLiteConnection(connectionString))
{
}
public SQLiteDataContext(IDbConnection connection) :
base(connection)
{
}
}

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 使用介绍的更多相关文章

  1. [安卓基础]011存储数据(中)——sqlite语法介绍

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  2. iOS开发数据库篇—SQLite简单介绍

    iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等. 说明:离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式 (1 ...

  3. 【转】 iOS开发数据库篇—SQLite简单介绍

    开始学SQLite啦, 原文: http://www.cnblogs.com/wendingding/p/3868893.html iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中 ...

  4. SQLite简单介绍

    一.离线缓存 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等. 说明:离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式 (1)归档:NSCodeing.NSKeyed ...

  5. Android中SQLite数据库操作(1)——使用SQL语句操作SQLite数据库

    下面是最原始的方法,用SQL语句操作数据库.后面的"Android中SQLite数据库操作(2)--SQLiteOpenHelper类"将介绍一种常用的android封装操作SQL ...

  6. AutoMapper之ABP项目中的使用介绍

    最近在研究ABP项目,昨天写了Castle Windsor常用介绍以及其在ABP项目的应用介绍 欢迎各位拍砖,有关ABP的介绍请看阳光铭睿 博客 AutoMapper只要用来数据转换,在园里已经有很多 ...

  7. iOS开发UI篇—iPad开发中得modal介绍

    iOS开发UI篇—iPad开发中得modal介绍 一.简单介绍 说明1: 在iPhone开发中,Modal是一种常见的切换控制器的方式 默认是从屏幕底部往上弹出,直到完全盖住后面的内容为止 说明2: ...

  8. objective-c 中的关联介绍

    objective-c 中的关联介绍 转载请注明CSDN博客上的出处: http://blog.csdn.net/daiyibo123/article/details/46471993 如何设置关联 ...

  9. ORACLE 中的 锁 介绍

    ORACLE 中的 锁 介绍 Oracle数据库支持多个用户同时与数据库进行交互,每个用户都可以同时运行自己的事务,从而也需要对并发访问进行控制.Oracle也是用“锁”的机制来防止各个事务之间的相互 ...

随机推荐

  1. mysql出错:Access denied for user 'root'@'localhost' (using password: YES)

    网站链接mysql数据库的时候,连接不上,并报出错误:Access denied for user 'root'@'localhost' (using password:YES) 这是个相当恼火的问题 ...

  2. SequenceInputStream

    SequenceInputStream从名字上看, 他是一个序列字节输入流 既然是个序列 那么意味着 SequenceInputStream装着许多的输入流 所以 可以用他来合并文件 Sequence ...

  3. Ionic 今天发布了Windows 桌面版的IDE Ionic Lab

    Ionic简介: Ionic 是一个强大的 HTML5 应用程序开发框架,号称 Advanced HTML5 Hybrid Mobile AppFramework 是 AngularJS 移动端解决方 ...

  4. Entity Framework 笔记(一)

    Entity Framework概述 EF是一个对象关系映射(ORM)框架,允许开发人员使用特定于域的对象关系型数据,开发人员通常不需要编写大量的数据访问代码.使用EF,开发者可以利用LINQ进行查询 ...

  5. Midnight.js – 实现奇妙的固定头部切换效果

    Midnight.js 是一款 jQuery 插件,在页面滚动的时候实现多个头设计之间的切换,所以你总是有一个头与它下面的内容层叠,看起来效果很不错. Midnight.js 可以让你轻松实现这种切换 ...

  6. Resumable.js – 基于 HTML5 File API 的文件上传

    Resumable.js 是一个 JavaScript 库,通过 HTML5 文件 API 提供,稳定和可恢复的批量上传功能.在上传大文件的时候通过每个文件分割成小块,每块在上传失败的时候,上传会不断 ...

  7. [js开源组件开发]模拟下拉选项框select

    模拟下拉选项框select 在css3流行的情况下,下拉框还是无法满足PD的需求,所以有了autosearch,有了模拟下拉框.效果如下图: select DEMO请案例点击这里查看.http://w ...

  8. HTTP与HTTPS握手的那些事

    今天我总结了什么是HTTP三次握手,还有HTTPS握手的过程以及为什么HTTPS是安全的. 前提 在讲述这两个握手时候,有一些东西需要提前说明. HTTP与TCP/IP区别? TPC/IP协议是传输层 ...

  9. 定制Eclipse IDE之杂症篇

    上文回顾:定制Eclipse IDE之插件篇(二) 该篇将讲述在开发Eclipse 插件过程发生的疑难杂症.不谈功能,只说病症. 前言.拿哪个Eclipse作为定制的基础? 我建议是你用哪个Eclip ...

  10. 如何通过CSS3 实现响应式Web设计

    如何通过CSS3 实现响应式Web设计: 分为三个步骤:(1)允许网页宽度自动调整.首先在页面头部中,我们需要加入这样一行:<meta name="viewport" con ...