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

简介: 原文:【C#】使用EF访问Sqlite数据库 1. 先上Nuget下载对应的包 如图,搜索System.Data.
原文: 【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

目录
相关文章
|
24天前
|
API 数据库 C语言
【C/C++ 数据库 sqlite3】SQLite C语言API返回值深入解析
【C/C++ 数据库 sqlite3】SQLite C语言API返回值深入解析
164 0
|
1月前
|
SQL 数据库 C#
C# .NET面试系列十一:数据库SQL查询(附建表语句)
#### 第1题 用一条 SQL 语句 查询出每门课都大于80 分的学生姓名 建表语句: ```sql create table tableA ( name varchar(10), kecheng varchar(10), fenshu int(11) ) DEFAULT CHARSET = 'utf8'; ``` 插入数据 ```sql insert into tableA values ('张三', '语文', 81); insert into tableA values ('张三', '数学', 75); insert into tableA values ('李四',
62 2
C# .NET面试系列十一:数据库SQL查询(附建表语句)
|
17天前
|
存储 NoSQL Java
Java数据库编程指南:实现高效数据存储与访问
【4月更文挑战第2天】Java开发者必须掌握数据库编程,尤其是JDBC,它是连接数据库的标准接口。使用Spring JDBC或JPA能简化操作。选择合适的JDBC驱动,如MySQL Connector/J,对性能至关重要。最佳实践包括事务管理、防SQL注入、优化索引和数据库设计。NoSQL数据库如MongoDB也日益重要,Java有对应的驱动支持。理解这些概念和技术是构建高效数据库应用的基础。
Java数据库编程指南:实现高效数据存储与访问
|
2月前
|
存储 监控 安全
内网屏幕监控软件的数据存储与管理:使用SQLite数据库保存监控记录和配置信息
在当今数字化时代,安全和监控在企业和组织中变得至关重要。内网屏幕监控软件作为一种关键工具,帮助组织监视员工的活动并确保信息安全。这种软件不仅需要高效地记录和管理监控数据,还需要能够方便地进行配置和调整。本文将讨论如何使用SQLite数据库来保存监控记录和配置信息,并介绍如何通过自动化机制将监控到的数据提交到指定网站。
150 2
|
3天前
|
SQL 缓存 Java
Java数据库连接池:优化数据库访问性能
【4月更文挑战第16天】本文探讨了Java数据库连接池的重要性和优势,它能减少延迟、提高效率并增强系统的可伸缩性和稳定性。通过选择如Apache DBCP、C3P0或HikariCP等连接池技术,并进行正确配置和集成,开发者可以优化数据库访问性能。此外,批处理、缓存、索引优化和SQL调整也是提升性能的有效手段。掌握数据库连接池的使用是优化Java企业级应用的关键。
|
6天前
|
SQL 关系型数据库 数据库
Python中SQLite数据库操作详解:利用sqlite3模块
【4月更文挑战第13天】在Python编程中,SQLite数据库是一个轻量级的关系型数据库管理系统,它包含在一个单一的文件内,不需要一个单独的服务器进程或操作系统级别的配置。由于其简单易用和高效性,SQLite经常作为应用程序的本地数据库解决方案。Python的内置sqlite3模块提供了与SQLite数据库交互的接口,使得在Python中操作SQLite数据库变得非常容易。
|
25天前
|
存储 SQL 数据库
C# 将 Word 转文本存储到数据库并进行管理
C# 将 Word 转文本存储到数据库并进行管理
|
29天前
|
SQL Java 关系型数据库
Java数据库访问
Java数据库访问
|
1月前
|
关系型数据库 数据库 C++
嵌入式数据库sqlite3【基础篇】基本命令操作,小白一看就懂(C/C++)
嵌入式数据库sqlite3【基础篇】基本命令操作,小白一看就懂(C/C++)
|
1月前
|
存储 SQL 数据库
django如何连接sqlite数据库?
django如何连接sqlite数据库?
38 0