原文:【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. [CSS Flex] Flex direction

    flex-direction: main two 'row' or 'column', you can use reverse also.

  2. C语言高速入门系列(五)

    C语言高速入门系列(五) C语言指针初涉                                           ------转载请注明出处:coder-pig 本节引言: 上一节我们对C ...

  3. hdu5389 Zero Escape

    Problem Description Zero Escape, is a visual novel adventure video game directed by Kotaro Uchikoshi ...

  4. [Ramda] Eliminate Function Arguments (Point-Free Style) with Ramda's Converge

    When doing comparisons inside of functions, you end of relying heavily on the argument passed into t ...

  5. 编程马拉松大赛试题及代码(C++实现)

    前段时间牛客网举办了编程马拉松大赛,总共86道题,20天内完毕. 题目难度难中易都有.我发现这些题目,主要关注性能和思维. 非常多题目用常规方法是不能通过时间要求的.题目是来自于各大oj以及面试题.所 ...

  6. WPF随笔(九)--使用路径动画模拟管道流体流向

    原文:WPF随笔(九)--使用路径动画模拟管道流体流向 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/lordwish/article/detail ...

  7. UE4.5.0的Kinect插件(Plugin)<一>

    声明:所有权利保留. 转载必须说明出处:http://blog.csdn.net/cartzhang/article/details/43193431 UE4 Plugin,在UE4的官网,放出了有个 ...

  8. Unity3d 配置OpenCV(EmguCV) 周围环境

    最近毕业.我们一直在研究如何Unity正在使用EmguCV,最后,有些吃老本的今天. 我的环境:Unity3d 4.3.1f             libemgucv-windows-univers ...

  9. MySQL数据库备份详解

    原文:MySQL数据库备份详解 对于任何数据库来说,备份都是非常重要的 数据库复制不能取代备份的作用 比如我们由于误操作,在主数据库上删除了一些数据,由于主从复制的时间很短,在发现时,从数据库上的数据 ...

  10. 到底有多少种智能指针(smart pointer)

    最近Qt的blog总结了到底有多少种smart pointer, 下面是一个简要的介绍: 1.   QPointer :提供对指针的保护,当一个指针被删除以后,再使用不会造成野指针或者指针溢出.比如 ...