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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM