SQLite 的 CodeFirst 模式
目前 EF 是 .NET 平台下相当成熟的 ORM 框架,但是其最新发布的 6.x 版本依然不支持 SQLite 的 CodeFirst 模式,好在有大神已经在 Nuget 上发布的相应的 Package 来解决这个问题。笔者通过做一个小实验来验证一下。
问题描述
SQLite 本身不支持 CodeFirst 模式,当我们的数据模型因业务变化而需要修改的话,那对应的数据库表也要进行更改。这个时候,如果我们手动修改数据表的话就不太方便,因此我们需要想办法让其支持 CodeFirst 模式。笔者通过使用 SQLite.CodeFirst 来尝试解决上述问题。
解决方案
安装依赖包
首先我们创建一个控制台程序,安装如下 Package:
- System.Data.SQLite
- SQLite.CodeFirst
修改程序配置 App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<!--新增结点-->
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite.EF6" />
<add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
<remove invariant="System.Data.SQLite" /><add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /></DbProviderFactories>
</system.data>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<!--新增结点-->
<providers>
<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
</providers>
</entityFramework>
<!--新增结点-->
<connectionStrings>
<add name="sampledb" connectionString="data source=.\sampledb.db" providerName="System.Data.SQLite" />
</connectionStrings>
</configuration>
创建模型对象 Person.cs
[Table("person")]
public class Person
{
[Column("id"), Key, Autoincrement]
public int Id { get; set; }
[Column("firstname")]
public string FirstName { get; set; }
[Column("lastname")]
public string LastName { get; set; }
}
创建数据上下文 PersonDbContext.cs
public class PersonDbContext : DbContext
{
public DbSet<Person> People { get; set; }
/// <summary>
/// 从配置文件读取链接字符串
/// </summary>
public PersonDbContext() :
base("name = sampledb")
{
ConfigurationFunc();
}
/// <summary>
/// 代码指定数据库连接
/// </summary>
/// <param name="existingConnection"></param>
/// <param name="contextOwnsConnection"></param>
public PersonDbContext(DbConnection existingConnection, bool contextOwnsConnection) :
base(existingConnection, contextOwnsConnection)
{
ConfigurationFunc();
}
private void ConfigurationFunc()
{
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = true;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var initializer = new SqliteDropCreateDatabaseWhenModelChanges<PersonDbContext>(modelBuilder);
Database.SetInitializer(initializer);
}
}
此时,当我们修改数据模型时,不需要执行任何 migration 操作就可以将 数据表映射到新的模型上。下面我们在主程序中调用一下:
主程序调用 Program.cs
class Program
{
static void Main(string[] args)
{
var ptah = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sampledb.db");
var connection = SQLiteProviderFactory.Instance.CreateConnection();
connection.ConnectionString = $"Data Source={ptah}";
//using (var context = new PersonDbContext())
using (var context = new PersonDbContext(connection, false))
{
#region 预热:针对数据表较多的情况下建议执行下述操作
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
var mappingColection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
mappingColection.GenerateViews(new List<EdmSchemaError>());
#endregion
#region 插入数据
Console.WriteLine("插入数据:");
context.People.Add(new Person { FirstName = "hippie", LastName = "zhou" });
context.SaveChanges();
#endregion
#region 查找数据
Console.WriteLine("查找数据:");
foreach (var people in context.People)
{
Console.WriteLine($"{people.Id} - {people.FirstName} - {people.LastName}");
}
#endregion
#region 更改数据
Console.WriteLine("更改数据:");
Person person = context.People.Where(p => p.Id == 1)?.FirstOrDefault();
person.LastName = "Puth";
context.SaveChanges();
#endregion
#region 删除数据
Console.WriteLine("删除数据:");
Person person = context.People.Where(p => p.Id == 1)?.FirstOrDefault();
context.People.Remove(person);
context.SaveChanges();
#endregion
Console.ReadKey();
}
}
}
注意事项
由于 SQLite.CodeFirst 的 Package 需要依赖 EntityFramework,以及为了能保证数据操作支持相关 LINQ 操作,在上述两个 Pacakge 安装的过程中,会同时安装其它依赖包,所以最终的项目依赖包如下所示:
- EntityFramework
- SQLite.CodeFirst
- System.Data.SQLite
- System.Data.SQLite.Core
- System.Data.SQLite.EF6
- System.Data.SQLite.Linq
此外,需要注意一下 System.Data.SQLite 与 System.Data.SQLite.Core 的区别:
System.Data.SQLite:The official SQLite database engine for both x86 and x64 along with the ADO.NET provider. This package includes support for LINQ and Entity Framework 6.
System.Data.SQLite.Core:The official SQLite database engine for both x86 and x64 along with the ADO.NET provider.
所以,为了能让 SQLite 支持 CodeFirst ,还是一件挺曲折的事情啊。
相关参考
SQLite 的 CodeFirst 模式的更多相关文章
- 【原创】EntityFramework Core 中使用 CodeFirst 模式时 PowerShell 版本问题及解决
一.描述: 在使用 Entity Framework Core 时,使用 CodeFirst 模式, 在 VS 中的 PMC(nuget 包管理 控制台) 控制台界面使用如下命令: Install-P ...
- 第十三节: EF的三种模式(三) 之 来自数据库的CodeFirst模式
一. 简介 [来自数据库的Code First模式]实质上并不是CodeFirst模式,而是DBFirst模式的轻量级版本,在该模式中取消了edmx模型和T4模板,直接生成了EF上下文和相应的类,该模 ...
- 第十四节: EF的三种模式(四) 之 原生正宗的 CodeFirst模式的默认约定
一. 简介 1. 正宗的CodeFirst模式是不含有edmx模型,需要手动创建实体.创建EF上下文,然后生成通过代码来自动映射生成数据库. 2. 旨在:忘记SQL.忘记数据库. 3. 三类配置:On ...
- 第十七节: EF的CodeFirst模式的四种初始化策略和通过Migration进行数据的迁移
一. 四种初始化策略 EF的CodeFirst模式下数据库的初始化有四种策略: 1. CreateDatabaseIfNotExists:EF的默认策略,数据库不存在,生成数据库:一旦model发生变 ...
- EF的CodeFirst模式自动迁移(适用于开发环境)
EF的CodeFirst模式自动迁移(适用于开发环境) 1.开启EF数据迁移功能 NuGet包管理器------>程序包管理控制台---------->Enable-Migrations ...
- GRDB使用SQLite的WAL模式
GRDB使用SQLite的WAL模式 WAL全称是Write Ahead Logging,它是SQLite中实现原子事务的一种机制.该模式是从SQLite 3.7.0版本引入的.再此之前,SQLi ...
- sqlite之WAL模式
链接 概述 在3.7.0以后,WAL(Write-Ahead Log)模式可以使用,是另一种实现事务原子性的方法. WAL的优点 在大多数情况下更快 并行性更高.因为读操作和写操作可以并行. 文件IO ...
- asp.net mvc CodeFirst模式数据库迁移步骤
利用Code First模式构建好基本的类后,项目也开始搭建完毕并成功运行,而且已经将数据库表结构自动生成了. 但是,我有新的类要加入,有字段需要修改,那怎么办呢,删库,跑路 ? 哈哈 利用数据库迁 ...
- 第十五节: EF的CodeFirst模式通过DataAnnotations修改默认协定
一. 简介 1. DataAnnotations说明:EF提供以特性的方式添加到 domain classes上,其中包括两类: A:System.ComponentModel.DataAnnota ...
随机推荐
- 微信公众号UX分析—— 学生作业小结
1. 不足: 1. 权威性:个人帐号,显得不够正式. 2. 排版问题: + 没有必要的外接端口,界面设计极度缺少排版.哪怕是个人公众号都不至于如此,更何况这是一个学校的教务平台. 3. 反应不及时或无 ...
- Visual Studio 代码片段
管理界面 打开 工具 >> 代码片段管理器 界面 使用步骤 选择对应语言. 选择一个片段的文件夹. 打开该文件夹的位置. 复制任意一个片段. 对复制出来的片段进行修改.(具体修改内容见例子 ...
- 47_并发编程-线程python实现
一.Threading模块 1.线程的创建 - 方式一 from threading import Thread import time def sayhi(name): time.sleep(2 ...
- ajax跨域问题小结
跨域:跨域名的访问,是浏览器对ajax的一种限制,这样可以有效的房子跨站攻击 跨域的范畴: 域名不同 或 端口不同 或 二级域名不同 解决方案: 第一种:由于前端基础薄弱,且该方式老掉牙,不讲解: ...
- 建立一个类似于天眼的Android应用程序:第4部分 - 持久收集联系人,通话记录和短信(SMS)
建立一个类似于天眼的Android应用程序:第4部分 - 持久收集联系人,通话记录和短信(SMS) 电话黑客android恶意软件编程黑客入侵linux 随着我们继续我们的系列,AMUNET应用程序变 ...
- 关于 SQL 注入的问题
拼串 (Statement)方式 1.编译次数多,效率比较低:会出现SQL注入问题(数据安全问题):先传参数再编译. 2.Sql文对应的字符串不一样,需要再次编译.Sql文对应的字符串一样,不会再编译 ...
- 如何在cygwin中运行crontab定时脚本[利刃篇]
用到cygwin,自然是希望能多处理一些类似linux的任务了,那就自然少不了定时任务crontab,看到网上教程不少,自己运行一个测试却也不那么容易,下面就记录我的安装过程,以供参考吧! 1.首先, ...
- 带你入门Python爬虫,8个常用爬虫技巧盘点
python作为一门高级编程语言,它的定位是优雅.明确和简单. 我学用python差不多一年时间了, 用得最多的还是各类爬虫脚本, 写过抓代理本机验证的脚本.写过论坛中自动登录自动发贴的脚本 写过自动 ...
- USB协议介绍
这里有必要先说清楚一下USB2.0规范的由来.USB2.0技术规范是有由Compaq.Hewlett Packard.Intel.Lucent.Microsoft.NEC.Philips共同制定.发布 ...
- JAVA中byte为负数处理
java中一定有人遇见过byte取值为负数情况,比如0xc0对应的值-64,其实应该是192,这里就需要我们转化处理 /** * Description: 负数byte转正int <BR> ...