VS2015 Winform使用SQLite的三种ORM方案
SQLite.Net-PCL
新建Winform项目,NuGet查找SQLite.Net-PCL,选择sqlite-net-pcl,注意,查找结果有好几个非常接近的,我们选择的程序包项目URL是https://github.com/praeclarum/sqlite-net,不要搞错了。
定义实体类:
public class Book
{
[PrimaryKey, AutoIncrement]
public int id { get; set; }
public string Name { get; set; }//书名
public DateTime PublishDate { get; set; }//出版日期
public string Author { get; set; }//作者
public float Price { get; set; }//价格
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
定义数据库,在数据库的构造函数中创建数据表:
public class MyBookDB : SQLiteConnection
{
//定义属性,便于外部访问数据表
public TableQuery<Book> Books { get { return this.Table<Book>(); } }
public MyBookDB(string dbPath) : base(dbPath)
{
//创建数据表
CreateTable<Book>();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Winform窗口设计非常简单,演示对数据库的增删改查,操作完成后,点击更新按钮,显示数据表全部记录,确认操作结果。表格控件用DataGridView。
Form1_Load初始化数据库文件路径:
//数据库文件路径
private string dbPath;
private void Form1_Load(object sender, EventArgs e)
{
//数据库文件路径就在运行目录下
dbPath = $"{Environment.CurrentDirectory}\\mybooks.db";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
增加
private void btnAdd_Click(object sender, EventArgs e)
{
List<Book> books = new List<Book>()
{
new Book() { Name = "射雕英雄传", PublishDate = new DateTime(1960, 1, 1), Author = "金庸", Price = 10.5f },
new Book() { Name = "神雕侠侣", PublishDate = new DateTime(1960, 2, 2), Author = "金庸", Price = 12.5f },
new Book() { Name = "倚天屠龙记", PublishDate = new DateTime(1960, 3, 3), Author = "金庸", Price = 16.5f },
new Book() { Name = "小李飞刀", PublishDate = new DateTime(1965, 5, 5), Author = "古龙", Price = 13.5f },
new Book() { Name = "绝代双骄", PublishDate = new DateTime(1965, 6, 6), Author = "古龙", Price = 15.5f },
};
using (var db = new MyBookDB(dbPath))
{
int count = db.InsertAll(books);
this.Text = $"{DateTime.Now}, 插入{count}条记录";
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
修改
private void btnModify_Click(object sender, EventArgs e)
{
using (var db = new MyBookDB(dbPath))
{
var book = db.Books.FirstOrDefault(x => x.Name == "绝代双骄");
if (book != null)
{
book.Price += 1;
int count = db.Update(book);
this.Text = $"{DateTime.Now}, 修改{count}条记录";
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
删除
private void btnDel_Click(object sender, EventArgs e)
{
using (var db = new MyBookDB(dbPath))
{
int count = db.Books.Delete(x => x.Name == "绝代双骄");
this.Text = $"{DateTime.Now}, 删除{count}条记录";
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
查询
private void btnQuery_Click(object sender, EventArgs e)
{
using (var db = new MyBookDB(dbPath))
{
var books = db.Books.Where(x => x.Author == "金庸").OrderByDescending(x => x.PublishDate).ToList();
this.Text = $"{DateTime.Now}, 查到{books.Count}条记录";
this.dataGridView1.DataSource = books;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
刷新
private void btnRefresh_Click(object sender, EventArgs e)
{
using (var db = new MyBookDB(dbPath))
{
var books = db.Books.ToList();
this.dataGridView1.DataSource = books;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
访问数据库的代码非常简单,类似EF,但是有一点点差异,数据表的类型是TableQuery,不是DBSet,所以增加、修改记录的函数有点差异。
System.Data.SQLite+SQLite.CodeFirst
新建Winform项目,NuGet安装System.Data.SQLite,它会自动安装EF6.0。
然后安装SQLite.CodeFirst,它会自动升级EF到6.1.0。一定要再把EF升级到6.1.3,否则运行会报错The type of the key field ‘id’ is expected to be ‘System.Int32’, but the value provided is actually of type ‘System.Int64’.
然后在App.Config中添加一行
<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" />
<!--手工添加下面一行-->
<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
</providers>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
然后添加数据库连接字符串
<connectionStrings>
<add name="dbConn" connectionString="data source=mytest1.db" providerName="System.Data.SQLite.EF6" />
</connectionStrings>
- 1
- 2
- 3
- 4
定义实体类,跟EF一样:
public class Book
{
public int id { get; set; }
public string Name { get; set; }//书名
public DateTime PublishDate { get; set; }//出版日期
public string Author { get; set; }//作者
public float Price { get; set; }//价格
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
定义数据库,在数据库的构造函数中创建数据表:
public class MyBookDB : DbContext
{
//定义属性,便于外部访问数据表
public DbSet<Book> Books { get { return Set<Book>(); } }
public MyBookDB() : base("dbConn")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//base.OnModelCreating(modelBuilder);
ModelConfiguration.Configure(modelBuilder);
var init = new SqliteCreateDatabaseIfNotExists<MyBookDB>(modelBuilder);
Database.SetInitializer(init);
}
}
public class ModelConfiguration
{
public static void Configure(DbModelBuilder modelBuilder)
{
ConfigureBookEntity(modelBuilder);
}
private static void ConfigureBookEntity(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
增删改查的代码跟EF一样:
private void btnAdd_Click(object sender, EventArgs e)
{
List<Book> books = new List<Book>()
{
new Book() { Name = "射雕英雄传", PublishDate = new DateTime(1960, 1, 1), Author = "金庸", Price = 10.5f },
new Book() { Name = "神雕侠侣", PublishDate = new DateTime(1960, 2, 2), Author = "金庸", Price = 12.5f },
new Book() { Name = "倚天屠龙记", PublishDate = new DateTime(1960, 3, 3), Author = "金庸", Price = 16.5f },
new Book() { Name = "小李飞刀", PublishDate = new DateTime(1965, 5, 5), Author = "古龙", Price = 13.5f },
new Book() { Name = "绝代双骄", PublishDate = new DateTime(1965, 6, 6), Author = "古龙", Price = 15.5f },
};
using (var db = new MyBookDB())
{
db.Books.AddRange(books);
int count = db.SaveChanges();
this.Text = $"{DateTime.Now}, 插入{count}条记录";
}
}
private void btnModify_Click(object sender, EventArgs e)
{
using (var db = new MyBookDB())
{
var book = db.Books.FirstOrDefault(x => x.Name == "绝代双骄");
if (book != null)
{
book.Price += 1;
int count = db.SaveChanges();
this.Text = $"{DateTime.Now}, 修改{count}条记录";
}
}
}
private void btnDel_Click(object sender, EventArgs e)
{
using (var db = new MyBookDB())
{
var book = db.Books.FirstOrDefault(x => x.Name == "绝代双骄");
if (book != null)
{
var result = db.Books.Remove(book);
int count = db.SaveChanges();
this.Text = $"{DateTime.Now}, 删除{count}条记录";
}
}
}
private void btnQuery_Click(object sender, EventArgs e)
{
using (var db = new MyBookDB())
{
var books = db.Books.Where(x => x.Author == "金庸").OrderByDescending(x => x.PublishDate).ToList();
this.Text = $"{DateTime.Now}, 查到{books.Count}条记录";
this.dataGridView1.DataSource = books;
}
}
private void btnRefresh_Click(object sender, EventArgs e)
{
using (var db = new MyBookDB())
{
var books = db.Books.ToList();
this.dataGridView1.DataSource = books;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
EF Core
重新打开VS2015,新建Winform项目,采用新的解决方案,NuGet安装Microsoft.EntityFrameworkCore.Sqlite。
然后安装Microsoft.EntityFrameworkCore.Tools。
定义实体类,跟EF一样:(同上)
定义数据库:
public class MyBookDB : DbContext
{
public DbSet<Book> Books { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlite("Filename=my1.db");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
增删改查的代码跟EF一样:(同上)
然后编译项目。
运行程序包管理器控制台
执行Add-Migration my1,系统自动创建了一个文件夹和2个文件
打开看看,有创建数据库的代码
public partial class my1 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Books",
columns: table => new
{
id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Author = table.Column<string>(nullable: true),
Name = table.Column<string>(nullable: true),
Price = table.Column<float>(nullable: false),
PublishDate = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Books", x => x.id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Books");
}
}
[DbContext(typeof(MyBookDB))]
partial class MyBookDBModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.1.2");
modelBuilder.Entity("EFCoreSqlite.Book", b =>
{
b.Property<int>("id")
.ValueGeneratedOnAdd();
b.Property<string>("Author");
b.Property<string>("Name");
b.Property<float>("Price");
b.Property<DateTime>("PublishDate");
b.HasKey("id");
b.ToTable("Books");
});
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
然后运行Update-Database,在程序运行目录下创建了my1.db。
然后就可以运行项目测试增删改查了。
注意:
1,不要直接在之前2个项目的解决方案中添加EF Core项目,否则Add-Migration会报错The EntityFramework package is not installed on project
2,Add-Migration之前先重新生成项目,否则报错Build failed。
小结
在Winform软件中,如果对数据库性能要求不高的话,可以使用SQLite,最大好处是减少安装包体积。如果采用SQL Server Express的话,安装包几百M,就算采用精简的LocalDB,安装包也有几十M,但是用SQLite打包,则只有几M。
对于SQLite.Net-PCL项目,用InstallShield打包时,注意勾选内容文件,否则会缺少e_sqlite3.dll文件。
SQLite.Net-PCL的好处是引入的库比较少,如果移动客户端采用Xamarin开发,可以实现PC客户端和移动客户端共享数据库模块的代码。坏处就是数据库访问代码跟EF标准不大一样。
System.Data.SQLite+SQLite.CodeFirst的好处就是访问数据库的代码完全等同EF,理论上可以更换数据库类型而不用修改上层代码。
EF Core则比较麻烦,不能自动化创建数据库,每次更改数据库还要手工输入命令升级数据库,而且引入的库非常多,感觉非常不爽。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现