【C#】使用EF访问Sqlite数据库
1. 先上Nuget下载对应的包
如图,搜索System.Data.SQLite下载安装即可,下载完之后带上依赖一共有这么几个:
- EntityFramework
- System.Data.SQLite
- System.Data.SQLite.Core
- System.Data.SQLite.EF6
- System.Data.SQLite.Linq
安装完成后,会添加App.config文件(如果没有的话),里面添加了一些provider的配置。
2. 先看下DB First模式
如果你用的是VS2017的话,很不幸无法通过“ADO.NET实体数据模型”来生成edmx文件。如果用VS2015及之前版本的话可以去官网下载一个插件,安装之后就可以用了。这里以VS2017为例:
1. 首先,在App.config中配置数据库连接字符串:
<connectionStrings>
<add name="SqliteTest" connectionString="Data Source=E:\retail.db" providerName="System.Data.SQLite.EF6" />
</connectionStrings>
2.然后就可以 编写数据库上下文和实体了,然后就可以用了
public class RetailContext : DbContext
{
public RetailContext(): base("SqliteTest"){}
public DbSet<Thumbnail> Thumbnails { set; get; }
}
public class Thumbnail
{
public Int64 Id { get; set; }
[Required]
[Unique]
public string OrginFilePath { get; set; }
[Required]
public string ThumbnailPath { get; set; }
[Required]
public DateTime LastUpdateTime { get; set; }
}
不过在运行过程中你可能会遇到这个错误SQLite error of “Unable to find the requested .Net Framework Data Provider.
解决方法就是在App.config的providers中添加以下节点
<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
完整的如下:
<providers>
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<!-- 1. Solves SQLite error of "Unable to find the requested .Net Framework Data Provider."-->
<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
</providers>
从上面的代码可以看到数据库的路径是写死的不能改变,这样就很不灵活。我喜欢可以动态连接的数据库,所以再次修改:
我们知道DbContext这个类有几个构造函数,一个是接收string类型的connectionString,一般都用的是这个。还有一个构造函数是接收一个DbConnection类型参数和bool类型的参数。这个构造函数就可以实现我们的要求:
- 首先,构造一个
DbConnection类:
DbConnection sqliteCon = SQLiteProviderFactory.Instance.CreateConnection(); - 然后,给这个对象设置
ConnectionString:
sqliteCon.ConnectionString = dbPath; 最后,把这个对象传给
DbContext即可。如下:
public class ThumbnailContext : DbContext
{
static string dbPath = $"Data Source=E:\\thumbnail.db";
public static ThumbnailContext Instance
{
get
{
DbConnection sqliteCon = SQLiteProviderFactory.Instance.CreateConnection();
sqliteCon.ConnectionString = dbPath;
return new ThumbnailContext(sqliteCon);
}
}
private ThumbnailContext(DbConnection con) : base(con, true) { }
public DbSet<Thumbnail> Thumbnails { get; set; }
}
3. CodeFirst模式
Sqlite默认不支持CodeFirst模式,如果用户因为某些操作删除了我们的db文件,此时我们的程序就不能正常工作了,是不是有点尴尬?不过还是有解决办法的,在Nuget里搜索SQLite.CodeFirst安装即可。
然后重写DbContext的OnModelCreating方法。这里是修改后的数据库上下文:
public class ThumbnailContext : DbContext
{
static string dbPath = $"Data Source={PathManager.AppDataTempThumbnail}\\thumbnail.db";
public static ThumbnailContext Instance
{
get
{
DbConnection sqliteCon = SQLiteProviderFactory.Instance.CreateConnection();
sqliteCon.ConnectionString = dbPath;
return new ThumbnailContext(sqliteCon);
}
}
private ThumbnailContext(DbConnection con) : base(con, true) { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//如果不存在数据库,则创建
Database.SetInitializer(new SqliteCreateDatabaseIfNotExists<ThumbnailContext>(modelBuilder));
}
public DbSet<Thumbnail> Thumbnails { get; set; }
}
4.一些优化
在使用过程中你可能会察觉到,每当第一次访问数据库(查询、插入等)时总是会慢一点,可能有1秒的时间数据库才会做出响应,然后接下再操作就很快。
这是因为当你第一次访问数据库时,EF需要在内存中建立实体与数据库表的映射关系,这个操作需要点时间。所以在你的程序一启动的时候就要把关系给映射好。
这里以上面的ThumbnailContext为例,首先new一个对象,假设为dbContext。然后在你整个应用程序的入口点调用下述代码:
public void Init()
{
//Pre-Generated Mapping Views
var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
mappingCollection.GenerateViews(new List<EdmSchemaError>());
}
后记:通过EF来访问Sqlite数据库,我也使用了有一段时间了,但是有时候会出现几个莫名奇妙的问题,而且还不太好定位,不知道是不是EF和Sqlite不太兼容的问题。现在尝试改为用ADO.NET来访问,于是就有了接下来的这篇文章:【C#】使用ADO.NET访问Sqlite数据库,SqliteHelper帮助类。
参考链接:
【C#】使用EF访问Sqlite数据库的更多相关文章
- 应用EF访问SQLite数据
创建项目,应用EF访问SQLite 1.创建项目 项目结构初始结构如下图所示,Netage.Data.SQLite 类库项目用于定义访问数据的接口和方法,Netage.SQLiteTest.UI 控制 ...
- 以EntifyFramework DBFirst方式访问SQLite数据库
前面一直在找EF Code First方式来访问SQLite数据库,后面得出的结论是SQLite不支持 Code First, 虽然有非官方的库SQLite.CodeFirst可以使用,但一直没搞成功 ...
- Qt5 开发 iOS 应用之访问 SQLite 数据库
开发环境: macOS 10.12.1 Xcode 8.1 Qt 5.8 iPhone 6S+iOS 10.1.1 源代码: 我在 Qt 程序里指定了数据库的名称来创建数据库,在 Win10.An ...
- 【Android】13.4 使用SQLite.NET.Async-PCL访问SQLite数据库
分类:C#.Android.VS2015: 创建日期:2016-02-27 一.简介 这一节演示如何利用以异步方式(async.await)访问SQLite数据库. 二.示例4运行截图 下面左图为初始 ...
- 【Android】13.2 使用自定义的CursorAdapter访问SQLite数据库
分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 SQliteDemo1的例子演示了SimpleCursorAdapter的用法,本节我们将使用用途更广的自定义的游 ...
- 【Android】13.1 用Android自带的API访问SQLite数据库
分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 这一节我们先来看看如何直接用Android自带的API创建和访问SQLite数据库. 1.创建SQLite数据库 ...
- 【Android】13.0 第13章 创建和访问SQLite数据库—本章示例主界面
分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 Android 内置了三种数据存取方式:SQLite数据库.文件.SharedPreferences. 这一章我们 ...
- 并发访问sqlite数据库出现databse is locked的错误的一个解决办法
作者:朱金灿 来源:http://blog.csdn.net/clever101 在并发访问sqlite数据库会出现这样一个错误:databseis locked,这是sqlite数据库对并发支持不太 ...
- EF操作sqlite数据库时的项目兼容性问题
问题:vs2015打不开vs2010建的操作sqlite的实体数据模型edmx文件 原因: 当前电脑必须先安装:驱动库及sqlite的vs拓展 正常情况下安装驱动和拓展后,vs2015就应该可以正常打 ...
随机推荐
- js进阶正则表达式10-分组-多行匹配-正则对象的属性(小括号作用:分组,将小括号里面的东西看成一个整体,因为量词只对前一个字符有效)(多行匹配:m)(属性使用:reg.global)
js进阶正则表达式10-分组-多行匹配-正则对象的属性(小括号作用:分组,将小括号里面的东西看成一个整体,因为量词只对前一个字符有效)(多行匹配:m)(属性使用:reg.global) 一.总结 1. ...
- 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(8)枚举、补码
一.枚举 # include <stdio.h> enum WeekDay //定义了一个数据类型(值只能写以下值) { MonDay, TuesDay, WednesDay, Thurs ...
- 【u015】兽径管理
[问题描述] 约翰农场的牛群希望能够在 N 个(1<=N<=200)草地之间任意移动.草地的编号由 1到N.草地之间有树林隔开.牛群希望能够选择草地间的路径,使牛群能够从任一 片草地移动到 ...
- Codeforces Round #313 (Div. 2) 560C Gerald's Hexagon(脑洞)
C. Gerald's Hexagon time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 前端切图:调用百度地图API
原型图 图片发自简书App <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- Undefined symbols for architecture i386: "_OBJC_CLASS_$_KKGridView", referenced from:
Undefined symbols for architecture i386: "_OBJC_CLASS_$_KKGridView", referenced from:
- 【bzoj3555】[Ctsc2014]企鹅QQ 简单哈希
传送门 题目分析 题意即求有多少对字符串只相差一个字符,枚举删除每个字符后的哈希, 看有多少相等即可. 比如有如下字符串:$Sd123$,其中S部分的哈希值为H,删除的是d,则原字符串的哈希值为$$( ...
- Lua转让C功能
在上一篇文章中(C调用lua函数)中.讲述了怎样用c语言调用lua函数,通常,A语言能调用B语言,反过来也是成立的.正如Java 与c语言之间使用JNI来互调.Lua与C也能够互调. 当lua调用c函 ...
- 【27.48%】【codeforces 699D】 Fix a Tree
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- [Scikit-Learn] - 数据预处理 - 缺失值(Missing Value)处理
reference : http://www.cnblogs.com/chaosimple/p/4153158.html 关于缺失值(missing value)的处理 在sklearn的prepro ...