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 ; }
}
定义数据库,在数据库的构造函数中创建数据表:
public class MyBookDB : SQLiteConnection
{
public TableQuery<Book> Books { get { return this .Table<Book>(); } }
public MyBookDB (string dbPath) : base (dbPath)
{
CreateTable<Book>();
}
}
Winform窗口设计非常简单,演示对数据库的增删改查,操作完成后,点击更新按钮,显示数据表全部记录,确认操作结果。表格控件用DataGridView。
Form1_Load初始化数据库文件路径:
private string dbPath;
private void Form1_Load (object sender, EventArgs e)
{
dbPath = $"{Environment.CurrentDirectory}\\mybooks.db" ;
}
增加
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}条记录" ;
}
}
修改
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}条记录" ;
}
}
}
删除
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}条记录" ;
}
}
查询
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;
}
}
刷新
private void btnRefresh_Click (object sender, EventArgs e)
{
using (var db = new MyBookDB(dbPath))
{
var books = db.Books.ToList();
this .dataGridView1.DataSource = books;
}
}
访问数据库的代码非常简单,类似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 >
然后添加数据库连接字符串
<connectionStrings >
<add name ="dbConn" connectionString ="data source=mytest1.db" providerName ="System.Data.SQLite.EF6" />
</connectionStrings >
定义实体类,跟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 ; }
}
定义数据库,在数据库的构造函数中创建数据表:
public class MyBookDB : DbContext
{
public DbSet<Book> Books { get { return Set<Book>(); } }
public MyBookDB () : base ("dbConn")
{
}
protected override void OnModelCreating (DbModelBuilder 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>();
}
}
增删改查的代码跟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.5 f },
new Book() { Name = "神雕侠侣" , PublishDate = new DateTime(1960 , 2 , 2 ), Author = "金庸" , Price = 12.5 f },
new Book() { Name = "倚天屠龙记" , PublishDate = new DateTime(1960 , 3 , 3 ), Author = "金庸" , Price = 16.5 f },
new Book() { Name = "小李飞刀" , PublishDate = new DateTime(1965 , 5 , 5 ), Author = "古龙" , Price = 13.5 f },
new Book() { Name = "绝代双骄" , PublishDate = new DateTime(1965 , 6 , 6 ), Author = "古龙" , Price = 15.5 f },
};
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;
}
}
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)
{
optionsBuilder.UseSqlite("Filename=my1.db" );
}
}
增删改查的代码跟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" );
});
}
}
然后运行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则比较麻烦,不能自动化创建数据库,每次更改数据库还要手工输入命令升级数据库,而且引入的库非常多,感觉非常不爽。