原文:【C#】使用EF访问Sqlite数据库

1. 先上Nuget下载对应的包



如图,搜索System.Data.SQLite下载安装即可,下载完之后带上依赖一共有这么几个:

  1. EntityFramework
  2. System.Data.SQLite
  3. System.Data.SQLite.Core
  4. System.Data.SQLite.EF6
  5. 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安装即可。



然后重写DbContextOnModelCreating方法。这里是修改后的数据库上下文:

    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帮助类


参考链接:

1. Sqlite3+EF6踩的坑

2. 让EntityFramework6支持SQLite

【C#】使用EF访问Sqlite数据库的更多相关文章

  1. 应用EF访问SQLite数据

    创建项目,应用EF访问SQLite 1.创建项目 项目结构初始结构如下图所示,Netage.Data.SQLite 类库项目用于定义访问数据的接口和方法,Netage.SQLiteTest.UI 控制 ...

  2. 以EntifyFramework DBFirst方式访问SQLite数据库

    前面一直在找EF Code First方式来访问SQLite数据库,后面得出的结论是SQLite不支持 Code First, 虽然有非官方的库SQLite.CodeFirst可以使用,但一直没搞成功 ...

  3. Qt5 开发 iOS 应用之访问 SQLite 数据库

    开发环境: macOS 10.12.1 Xcode 8.1 Qt 5.8 iPhone 6S+iOS 10.1.1   源代码: 我在 Qt 程序里指定了数据库的名称来创建数据库,在 Win10.An ...

  4. 【Android】13.4 使用SQLite.NET.Async-PCL访问SQLite数据库

    分类:C#.Android.VS2015: 创建日期:2016-02-27 一.简介 这一节演示如何利用以异步方式(async.await)访问SQLite数据库. 二.示例4运行截图 下面左图为初始 ...

  5. 【Android】13.2 使用自定义的CursorAdapter访问SQLite数据库

    分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 SQliteDemo1的例子演示了SimpleCursorAdapter的用法,本节我们将使用用途更广的自定义的游 ...

  6. 【Android】13.1 用Android自带的API访问SQLite数据库

    分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 这一节我们先来看看如何直接用Android自带的API创建和访问SQLite数据库. 1.创建SQLite数据库 ...

  7. 【Android】13.0 第13章 创建和访问SQLite数据库—本章示例主界面

    分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 Android 内置了三种数据存取方式:SQLite数据库.文件.SharedPreferences. 这一章我们 ...

  8. 并发访问sqlite数据库出现databse is locked的错误的一个解决办法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 在并发访问sqlite数据库会出现这样一个错误:databseis locked,这是sqlite数据库对并发支持不太 ...

  9. EF操作sqlite数据库时的项目兼容性问题

    问题:vs2015打不开vs2010建的操作sqlite的实体数据模型edmx文件 原因: 当前电脑必须先安装:驱动库及sqlite的vs拓展 正常情况下安装驱动和拓展后,vs2015就应该可以正常打 ...

随机推荐

  1. php课程 4-17 数组键值操作函数有哪些

    php课程 4-17  数组键值操作函数有哪些 一.总结 一句话总结:多看学习视频 1.php中数组的键值操作函数有哪6个? • array_values();获取数组中的值• array_keys( ...

  2. 从show slave status 中1062错误提示信息找到binlog的SQL

    mysql> show slave status\G *************************** 1. row *************************** Slave_I ...

  3. Redis的增删改查命令总结与持久化方式

    原文:Redis的增删改查命令总结与持久化方式 Redis是用C语言实现的,一般来说C语言实现的程序"距离"操作系统更近,执行速度相对会更快. Redis使用了单线程架构,预防了多 ...

  4. produces在@requestMapping中的使用方式和作用

    produces可能不算一个注解,因为什么呢,它是注解@requestMapping注解里面的属性项, 它的作用是指定返回值类型,不但可以设置返回值类型还可以设定返回值的字符编码: 还有一个属性与其对 ...

  5. 【t077】宝物筛选

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物--这下小FF可发财了.但是这里的宝物实在是太多 ...

  6. Erlang 聊天室程序

    Erlang 聊天室程序( 一) Erlang 聊天室程序(二) 客户端的退出 Erlang 聊天室程序(三) 数据交换格式---json的decode Erlang 聊天室程序(四) 数据交换格式- ...

  7. virtualenv对python

    使用virtualenv对python进行多版本隔离 最近在用python做一个文本的情感分析的项目,用到tensorflow,需要用python3的版本,之前因为<机器学习实战>那本书的 ...

  8. 【z01】铺地毯

    [问题描述] 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标 系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照 编号从小到大的顺 ...

  9. activity-alias详解及应用

    activity-alias标签元素众所周知,AndroidManifest是一个xml文件,它包含很多标签元素,如application.activity.receiver等,其中有一个叫做acti ...

  10. [UWP]使用Acrylic(亚克力)

    原文:[UWP]使用Acrylic(亚克力) 1. 前言 在 如何使用Fluent Design System 这篇文章里已经简单介绍过Reveal的用法,这篇再详细介绍其它内容. 自Windows ...