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則比較麻煩,不能自動化創建數據庫,每次更改數據庫還要手工輸入命令升級數據庫,而且引入的庫非常多,感覺非常不爽。