3 数据持久化
0 场景
软件跟一个设备可以通讯了,设备返回一些数据,我希望把这些数据存储起来,下次打开软件的时候能够浏览这次的数据
1 为什么使用数据库
磁盘存储数据是通过磁阻变化存储数据的
硬件设备上的信息存储是寄存器存储的
而我们想存储的数据是通过数据库存储的,因为查询效率高,如果是文件形式存储的话,想读一个数据只有把它之前的所有数据都读取才行,这样效率很慢。
但有时候我们也会把一些设置放在文件里:
比如说读取版本号,这跟业务逻辑无关,只需要升级程序读取,那么就不需要引用一堆数据库操作的库。
比如设置语言,一台电脑两个用户用,一个用中文,一个用英文,一个语言字段需要对应两个用户,那么最好的办法就是把语言配置文件放在每个用户下的AppData文件目录。
比如我们开放一些字段可以用户自己修改,而不需要操作数据库。
2 连接数据库
我们使用ORM框架去连接数据库。
什么是ORM?
软件跟数据库通讯的思路是:
1 我们去数据库查询是通过数据库认识的SQL语句查询的,我们要写SQL语句去查询数据
1 我们去数据库查询是通过数据库认识的SQL语句查询的,我们要写SQL语句去查询数据
2 数据查出来之后我们需要构建一个个对应的类,创建这些类的对象去承载这些数据结构,
3 软件调用这些对象去进行计算,显示。
ORM框架(这里只Entity Framework)帮我们完成了上面的三步。
通过ORM框架你只需要:
创建数据的承载类,之后调用ORM框架的查询方法就能获取查询对象。
推荐用微软官方的ORM 框架Entity Framework去连接数据库,功能够强大,追求轻量化会写SQL的可以用Dapper,或者一些其他的国产SQL SUGAR /FREE SQL
Entity Framework Code First模式
Code First模式省去了你去建库建表的时间,你只需要把数据类型设计出来,EF会根据你设计的数据类去自动构建,后期如果你修改了模型,ef也会根据魔性的修改响应修改数据库,简而言之,数据库这方面不用你操心了,写好自己的代码就ok。
3 EF Code First实战
1 Nuget安装框架库
-
System.Data.SQLite
-
SQLite.CodeFirst
2 改动一下app.config
- 在providers下再添加System.Data.SQLite节点
<entityFramework>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6"/>
<!--新增-->
<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6"/>
</providers>
</entityFramework>
- configuration下添加新的连接字符串节点connectionStrings
<connectionStrings>
<add name="MySqlite" connectionString="data source=.Local.db" providerName="System.Data.SQLite.EF6"/>
</connectionStrings>
- 以下为完整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 -->
<!-- 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>
<entityFramework>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6"/>
<!--新增-->
<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6"/>
</providers>
</entityFramework>
<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>
<!--新增-->
<connectionStrings>
<add name="MySqlite" connectionString="data source=.Local.db" providerName="System.Data.SQLite.EF6"/>
</connectionStrings>
</configuration>
2 建立数据模型
这个模型类方便软件内调用,也为了承载数据库查询出来的数据
public class Category
{
public string CategoryId { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public string CategoryId { get; set; }
public virtual Category Category { get; set; }
}
3 建立DBContext
DBContext是实体类与数据库之间的桥梁,通过这个类去查询数据,并返回对象。
public class ProductContext : DbContext
{
public ProductContext():base("name=MySqlite")
{ }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var initializer = new SqliteDropCreateDatabaseWhenModelChanges<MyDbContext>(modelBuilder);
Database.SetInitializer(initializer);
}
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
name=MySqlite 对应上文app.config里面的connectionStrings.Name
启动Main()
class Program
{
static void Main(string[] args)
{
using (var db = new ProductContext())
{
// 增
var food = new Category { CategoryId = "FOOD", Name = "Foods" };
db.Categories.Add(food);
int recordsAffected = db.SaveChanges();
Console.WriteLine("Saved {0} entities to the database, press any key to exit.", recordsAffected);
Console.ReadKey();
}
}
}
此时做了两步操作:
1 创建Local数据库并按照ProductContext里面的两个DbSet,分别按照模型建立Categories和Products两张表
2 在Category表里添加一个新的Category行
参考app.config里面设置的数据库位置connectionString="data source=.Local.db"
我们可以看到数据库已经自己生成,并按照我们想要的添加了一行新的数据
至此,数据存储方面算是跑通了,我们只需要关注于代码中的数据模型就ok了。
参考
https://docs.microsoft.com/en-us/ef/ef6/fundamentals/configuring/connection-strings
https://www.cnblogs.com/hippieZhou/archive/2018/08/04/9420432.html