UWP开发之ORM实践:如何使用Entity Framework Core做SQLite数据持久层?
选择SQLite的理由
在做UWP开发的时候我们首选的本地数据库一般都是Sqlite,我以前也不知道为啥?后来仔细研究了一下也是有原因的:
1,微软做的UWP应用大部分也是用Sqlite。或者说是微软推荐使用Sqlite吧!
2,简单!就只有一个类库没有多余的参照什么的。不像其他数据库还得做复杂配置什么的麻烦!
3,不需要数据库服务,数据服务和客户都在同一个进程里面。如下图:

4,作为存储系统它只支持一个用户一个数据实体。
5,跨平台跨结构,这个好!
Sqlite主要使用内容
如果想充分使用好Sqlite数据库,建议保存好下面两个链接
- The database connection handle
- The prepared statement object
操作上面对象主要的6个接口 - sqlite3_open()
- sqlite3_prepare()
- sqlite3_step()
- sqlite3_column()
- sqlite3_finalize()
- sqlite3_close()
SQLite数据持久层:Entity Framework Core
随着Entity Framework开源在.Net开发中越来越受欢迎,包括WinFrom,Asp.net MVC开发等等。为了跨平台在6.0后就是Entity Framwork Core版本。开源地址:https://github.com/aspnet/EntityFramework。
使用Entity Framwork Core当然得有个驱动才能调用SQLite数据库,那就是SQLite的ADO.NET驱动。大概层次如下:

ORM具体实现
此处做一个显示课程列表信息的UWP做实例。源代码:https://github.com/NewBLife/UWP/tree/master/SqliteEFCoreDemo。
1,新建一个空的UWP项目叫SqliteEFCoreDemo。
2,添加包引用。
Install-Package EntityFramework.SQLite –Pre
Install-Package EntityFramework.Commands –Pre

3,创建Student和Course的Entity。
// ***********************************************************************
// FileName:Course
// Description:
// Project:
// Author:NewBLife
// Created:2016/5/28 21:25:32
// Copyright (c) 2016 NewBLife,All rights reserved.
// *********************************************************************** using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace SqliteEFCoreDemo.Models
{
/// <summary>
/// 设置数据库表名
/// </summary>
[Table(name: "Course")]
public class Course
{
/// <summary>
/// ID不为空设置为Required
/// </summary>
[Required]
public string ID { get; set; }
public string Name { get; set; }
}
}// ***********************************************************************
// FileName:Student
// Description:
// Project:
// Author:NewBLife
// Created:2016/5/28 21:23:45
// Copyright (c) 2016 NewBLife,All rights reserved.
// ***********************************************************************
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace SqliteEFCoreDemo.Models
{
/// <summary>
/// 设置数据库表名
/// </summary>
[Table(name: "Student")]
public class Student
{
/// <summary>
/// ID不为空设置为Required
/// </summary>
[Required]
public string ID { get; set; } public string Name { get; set; } public List<Course> Courses { get; set; }
}
}4,创建数据库操作EfDbContext继承于Microsoft.Data.Entity.DbContext。
// ***********************************************************************
// FileName:EfDbContext
// Description:
// Project:
// Author:NewBLife
// Created:2016/5/28 21:32:23
// Copyright (c) 2016 NewBLife,All rights reserved.
// ***********************************************************************
using Microsoft.Data.Entity; namespace SqliteEFCoreDemo.Models
{
public class EfDbContext : DbContext
{
/// <summary>
/// 注意:如果Student的Model里面没有设置表名将使用Students作为表名
/// </summary>
public DbSet<Student> Students { get; set; }
public DbSet<Course> Courses { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// 配置数据库名
optionsBuilder.UseSqlite("Filename=School.db");}
}
}5,编译项目(非常重要,不然有可能后续步骤出错)。
6,高级操作:创建差分文件Migration。通过查看差分文件可以判断生成的表结构或者数据是不是正确(这是Entity Framework进行CodeFirst开发的便捷之处)。
在程序包管理器中执行:add-migration initDb。将自动创建下图红色部分内容(这就是Entity Framework强大之处)。

自动生成的表结构代码如下:
using System;
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Migrations;
using SqliteEFCoreDemo.Models; namespace SqliteEFCoreDemo.Migrations
{
[DbContext(typeof(EfDbContext))]
partial class EfDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "7.0.0-rc1-16348"); modelBuilder.Entity("SqliteEFCoreDemo.Models.Course", b =>
{
b.Property<string>("ID"); b.Property<string>("Name"); b.Property<string>("StudentID"); b.HasKey("ID"); b.HasAnnotation("Relational:TableName", "Course");
}); modelBuilder.Entity("SqliteEFCoreDemo.Models.Student", b =>
{
b.Property<string>("ID"); b.Property<string>("Name"); b.HasKey("ID"); b.HasAnnotation("Relational:TableName", "Student");
}); modelBuilder.Entity("SqliteEFCoreDemo.Models.Course", b =>
{
b.HasOne("SqliteEFCoreDemo.Models.Student")
.WithMany()
.HasForeignKey("StudentID");
});
}
}
}自动生成的数据更新代码如下:
using System;
using System.Collections.Generic;
using Microsoft.Data.Entity.Migrations; namespace SqliteEFCoreDemo.Migrations
{
public partial class initDb : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Student",
columns: table => new
{
ID = table.Column<string>(nullable: false),
Name = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Student", x => x.ID);
});
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
ID = table.Column<string>(nullable: false),
Name = table.Column<string>(nullable: true),
StudentID = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.ID);
table.ForeignKey(
name: "FK_Course_Student_StudentID",
column: x => x.StudentID,
principalTable: "Student",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
});
} protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable("Course");
migrationBuilder.DropTable("Student");
}
}
}每次执行Add-Migration 名称 都会根据你的Model修改创建差分的Migration文件。
7,重量级操作:在App.xaml.cs的构造方法中添加如下代码来生成真正的数据库文件。
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending; using (var db = new EfDbContext())
{
// 将差分文件写入数据库文件
db.Database.Migrate();
}
}8,添加演示布局以及Model的绑定设置。
<Page
x:Class="SqliteEFCoreDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SqliteEFCoreDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:data="using:SqliteEFCoreDemo.Models"
mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<RelativePanel HorizontalAlignment="Center" Margin="0,50,0,0">
<Grid Name="Header" Width="">
<Grid.RowDefinitions>
<RowDefinition Height=""/>
<RowDefinition Height=""/>
<RowDefinition Height=""/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=""/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Name="lblCID"
Grid.Column=""
Grid.Row=""
Text="课程ID:"/>
<TextBox Name="txbCId"
Grid.Column=""
Grid.Row=""
Width=""/>
<TextBlock Name="lblCName"
Grid.Column=""
Grid.Row=""
Text="课程名称:"/>
<TextBox Name="txbCName"
Width=""
Grid.Column=""
Grid.Row="" />
<Button Name="btnAdd"
Grid.Column=""
Grid.Row=""
Width=""
Click="btnAdd_Click"
Content="Add Course"/>
</Grid>
<Grid Name="List"
RelativePanel.Below="Header">
<ListView Name="lstCourse">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:Course">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=""/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="" Text="{x:Bind ID,Mode=OneWay}"/>
<TextBlock Grid.Column="" Text="{x:Bind Name,Mode=OneWay}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</RelativePanel>
</Grid>
</Page>using System.Linq;
using SqliteEFCoreDemo.Models;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; //“空白页”项模板在 http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 上有介绍 namespace SqliteEFCoreDemo
{
/// <summary>
/// 可用于自身或导航至 Frame 内部的空白页。
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
} private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
using (var db = new EfDbContext())
{
lstCourse.ItemsSource = db.Courses.ToList();
}
} private void btnAdd_Click(object sender, RoutedEventArgs e)
{
using (var db = new EfDbContext())
{
var newCourse = new Course
{
ID = txbCId.Text.Trim(),
Name = txbCName.Text.Trim()
}; txbCId.Text = string.Empty;
txbCName.Text = string.Empty; db.Courses.Add(newCourse);
db.SaveChanges(); lstCourse.ItemsSource = db.Courses.ToList();
}
}
}
}9,启动应用,添加数据试试。

10,查看自动创建的数据库文件。
Not Null设置,外键设置等等都自动设置好了!好强大有没有…

总结
用EFCore做数据库持久层只需要面向对象模型做处理就可以,与数据模型的交互等交给Entity Framework Core处理。总的来说使用很方便,节省不少工作量。
UWP开发之ORM实践:如何使用Entity Framework Core做SQLite数据持久层?的更多相关文章
- UWP开发之Template10实践二:拍照功能你合理使用了吗?(TempState临时目录问题)
最近在忙Asp.Net MVC开发一直没空更新UWP这块,不过有时间的话还是需要将自己的经验和大家分享下,以求共同进步. 在上章[UWP开发之Template10实践:本地文件与照相机文件操作的MVV ...
- UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)
前面[UWP开发之Mvvmlight实践五:SuspensionManager中断挂起以及复原处理]章节已经提到过Template10,为了认识MvvmLight的区别特做了此实例. 原代码地址:ht ...
- UWP开发之Mvvmlight实践七:如何查找设备(Mobile模拟器、实体手机、PC)中应用的Log等文件
在开发中或者后期测试乃至最后交付使用的时候,如果应用出问题了我们一般的做法就是查看Log文件.上章也提到了查看Log文件,这章重点讲解下如何查看Log文件?如何找到我们需要的Packages安装包目录 ...
- UWP开发之Mvvmlight实践九:基于MVVM的项目架构分享
在前几章介绍了不少MVVM以及Mvvmlight实例,那实际企业开发中将以那种架构开发比较好?怎样分层开发才能节省成本? 本文特别分享实际企业项目开发中使用过的项目架构,欢迎参照使用!有不好的地方欢迎 ...
- UWP: 在 UWP 中使用 Entity Framework Core 操作 SQLite 数据库
在应用中使用 SQLite 数据库来存储数据是相当常见的.在 UWP 平台中要使用 SQLite,一般会使用 SQLite for Universal Windows Platform 和 SQLit ...
- UWP开发之Mvvmlight实践二:Mvvmlight的核心框架MVVM与MVC、MVP的区别(图文详解)
最近UWP开发在海外很潮流,随着微软收购Xamarin,我们这些C#程序员也可以靠这杆小米枪挑战Android,IOS平台了. 那我们为什么选择MVVM做UWP开发?MVC,MVP,MVVM他们之间到 ...
- UWP开发之Mvvmlight实践八:为什么事件注销处理要写在OnNavigatingFrom中
前一段开发UWP应用的时候因为系统返回按钮事件(SystemNavigationManager.GetForCurrentView().BackRequested)浪费了不少时间.现象就是在手机版的详 ...
- UWP开发之Mvvmlight实践六:MissingMetadataException解决办法(.Net Native下Default.rd.xml配置问题)
最近完成一款UWP应用,在手机端测试发布版(Release)的时候应用莫名奇妙的强行关闭,而同样的应用包在PC端一点问题都没有,而且Debug版在两个平台都没有问题,唯独手机的Release版有问题. ...
- UWP开发之Mvvmlight实践五:SuspensionManager中断挂起以及复原处理
最近比较忙有一段时间没有更新了,再接再厉继续分享. 案例下载:https://github.com/NewBLife/UWP/tree/master/SuspendSample 先我们看看App在生命 ...
随机推荐
- 关于DOM的操作以及性能优化问题-重绘重排
写在前面: 大家都知道DOM的操作很昂贵. 然后贵在什么地方呢? 一.访问DOM元素 二.修改DOM引起的重绘重排 一.访问DOM 像书上的比喻:把DOM和JavaScript(这里指ECMScri ...
- ExtJS 4.2 组件介绍
目录 1. 介绍 1.1 说明 1.2 组件分类 1.3 组件名称 1.4 组件结构 2. 组件的创建方式 2.1 Ext.create()创建 2.2 xtype创建 1. 介绍 1.1 说明 Ex ...
- Nginx如何处理一个请求
看了下nginx的官方文档,其中nginx如何处理一个请求讲解的很好,现在贴出来分享下.Nginx首先选定由哪一个虚拟主机来处理请求.让我们从一个简单的配置(其中全部3个虚拟主机都在端口*:80上监听 ...
- Kooboo CMS技术文档之二:Kooboo CMS的安装步骤
在IIS上安装Kooboo CMS Kooboo CMS安装之后 安装的常见问题 1. 在IIS上安装Kooboo CMS Kooboo CMS部署到正式环境相当简单,安装过程是一个普通MVC站点在I ...
- mysql进阶之存储过程
往往看别人的代码会有这样的感慨: 看不懂 理还乱 是离愁 别是一番滋味在心头 为什么要使用存储过程? 在mysql开发中使用存储过程的理由: 当希望在不同的应用程序或平台上执行相同的函数,或者封装特定 ...
- PayPal高级工程总监:读完这100篇论文 就能成大数据高手(附论文下载)
100 open source Big Data architecture papers for data professionals. 读完这100篇论文 就能成大数据高手 作者 白宁超 2016年 ...
- js学习之函数的参数传递
我们都知道在 ECMAScript 中,数据类型分为原始类型(又称值类型/基本类型)和引用类型(又称对象类型):这里我将按照这两种类型分别对函数进行传参,看一下到底发生了什么. 参数的理解 首先,我们 ...
- BPM合同管理解决方案分享
一.方案概述合同是组织与组织间所订协议的法律 表现形式,体现着双方对于合作在法律和道德上的承诺.然而,大多数企业的合同管理都或多或少存在合同审批过程不规范.签订草率.审批权责不清.合同执行跟踪难.合同 ...
- 【干货分享】流程DEMO-合同会审表
流程名: 合同会审表 业务描述: 合同的审批及签订 流程相关文件: 流程包.xml 事务呈批表业务服务.xml 事务呈批表主数据.xml 流程说明: 1.此流程必须先进行事务呈批表流程的配置才可 ...
- mysql源码包手动安装、配置以及测试(亲测可行)
笔记编者:小波/qq463431476博客首页:http://www.cnblogs.com/xiaobo-Linux/ 记下这篇mysql笔记,望日后有用! redhat6采用centos yum源 ...