原文:【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. mysql mha高可用架构的安装

    MMM无法全然地保证数据的一致性,所以MMM适用于对数据的一致性要求不是非常高.可是又想最大程度的保证业务可用性的场景对于那些对数据一致性要求非常高的业务,非常不建议採用MMM的这样的高可用性架构.那 ...

  2. VBA Code for Word Navigation Pane 【failed】 view-showheading-method-word

    https://msdn.microsoft.com/VBA/Word-VBA/articles/view-showheading-method-word View.ShowHeading Metho ...

  3. SpringMVC中跳转路径的问题

    1. @RequestMapping 1)@RequestMapping既可以作用于类,也可以作用于方法 2)@RequestMapping中value值(即跳转的路径),可以加 "/&qu ...

  4. oracle 内存结构具体解释

    Oracle 内存结构 与 Oracle 实例关联的基本内存结构包含: 系统全局区 (SGA):由全部server和后台进程共享.SGA 中存储的数据演示样例包含快速缓存的数据块和共享 SQL 区域. ...

  5. Fastjson 序列化,反序列化Map对象排序问题(字符串转map,map转字符串)

    背景 记录项目中遇到的 关于fastjson jsonobject转string乱序,string转jsonObject乱序问题的解决方案 fastJson issues 问题来源描述参见: http ...

  6. java常用api2

    calendar calendar=calendar.getInstance(); StringBuilder和C#的用法一样 hashSet无序的,不可重复 LInkedHashSet有序的,不可重 ...

  7. 【Cocos2d-x Lua】数据库封装类型的操作

    Lua数据库封装类型的操作 使用演示样例 lua代码: require("DB") -- 保存一个字符串(数据库中存储的数据都是以字符串的形式保存的) DB:getInstance ...

  8. 使用JScript编译指定目录下所有工程

    作者:朱金灿 来源:http://blog.csdn.net/clever101 我遇到这样一个问题:在一个插件工程目录下的插件工程越来越多,因此通过建一个解决方案然后把新增加的工程逐个添加进解决方案 ...

  9. 理解 iOS 和 macOS 的内存管理

    在 iOS 和 macOS 应用的开发中,无论是使用 Objective-C 还是使用 swift 都是通过引用计数策略来进行内存管理的,但是在日常开发中80%(这里,我瞎说的,8020 原则嘛

  10. Linux socket编程示例(最简单的TCP和UDP两个例子)

    一.socket编程 网络功能是Uinux/Linux的一个重要特点,有着悠久的历史,因此有一个非常固定的编程套路. 基于TCP的网络编程: 基于连接, 在交互过程中, 服务器和客户端要保持连接, 不 ...