# Avalonia 使用EFCore調用SQLite實現Singleton全局註冊 ![image-20230720204001797](https://www.raokun.top/upload/2023/07/image-20230720204001797.png) 本篇博客是我的開源項目[T ...
Avalonia 使用EFCore調用SQLite實現Singleton全局註冊
本篇博客是我的開源項目TerraMours.Chat.Ava的更新的記錄分享,本次更新使用EntityFrameWork Core調用SQLite,實現數據的本地化和查詢的優化,刪除了dbpross類(直接調用SQLite的操作類)。大大提高了代碼的簡潔度和易讀性。通過全局註冊的ChatDbcontext對象,是操作資料庫變的非常方便。對項目感興趣的同學可以到github上搜索TerraMours.Chat.Ava。希望通過該項目瞭解和學習Avalonia開發的朋友可以在我的github上拉取代碼,同時希望大家多多點點star。
https://github.com/raokun/TerraMours.Chat.Ava
項目的基礎通用功能和業務代碼開發在之前博客中介紹過了,想瞭解的同學跳轉學習:
基於Avalonia 11.0.0+ReactiveUI 的跨平臺項目開發1-通用框架
基於Avalonia 11.0.0+ReactiveUI 的跨平臺項目開發2-功能開發
瞭解Avalonia創建模板項目-基礎可跳轉:
本次我主要分享的內容是項目中使用EFCore調用SQLite的實現。
1.安裝nuget包
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0-preview.6.23329.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0-preview.6.23329.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
2.創建一個繼承自 DbContext
的類
創建ChatDbcontext繼承自 DbContext
的類,併在構造函數中將連接字元串傳遞給 DbContextOptions
對象。
代碼如下:
public class ChatDbcontext :DbContext{
public DbSet<ChatMessage> ChatMessages { get; set; }
public DbSet<ChatList> ChatLists { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite($"Data Source={AppSettings.Instance.DbPath}"); // 這裡是您的 SQLite 連接字元串
protected override void OnModelCreating(ModelBuilder modelBuilder) {
// 添加實體配置
modelBuilder.Entity<ChatMessage>().HasKey(e => e.ChatRecordId);
modelBuilder.Entity<ChatList>().HasKey(e => e.Id);
base.OnModelCreating(modelBuilder);
}
//切換資料庫連接
public void ChangeConnection(string connectionString) {
// 修改資料庫連接字元串,並重新配置 DbContext
Database.GetDbConnection().ConnectionString = connectionString;
ChangeTracker.AutoDetectChangesEnabled = false;
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
ChangeTracker.AutoDetectChangesEnabled = true;
}
/// <summary>
/// 檢查表是否存在
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public bool CheckIfTableExists<T>() where T : class {
var tableExists = this.Model.FindEntityType(typeof(T)) != null;
return tableExists;
}
}
其中包括:
- OnConfiguring 根據配置文件中的資料庫地址設置資料庫連接
- OnModelCreating 中設置實體類的主鍵
- ChangeConnection 方法實現切換資料庫連接
- CheckIfTableExists 方法 檢查指定的表是否存在
3.DbContext 註冊為全局服務
1.創建一個靜態欄位
VMLocator類中,創建一個靜態欄位來保存 DbContext 的實例
代碼如下:
private static ChatDbcontext _chatDbcontext;
public static ChatDbcontext ChatDbcontext {
get => (_chatDbcontext ??= new ChatDbcontext());
set => _chatDbcontext = value;
}
2.創建ChatProcess資料庫操作類
代碼如下:
/// <summary>
/// 創建並初始化資料庫
/// </summary>
public void CreateDatabase() {
using (var context = new ChatDbcontext()) {
context.Database.Migrate();
VMLocator.ChatDbcontext = context;
}
}
/// <summary>
/// 判斷載入的資料庫表是否完整
/// </summary>
public async Task<bool> CheckTableExists(string selectedFilePath) {
VMLocator.ChatDbcontext.ChangeConnection(selectedFilePath);
return (VMLocator.ChatDbcontext.CheckIfTableExists<ChatMessage>() && VMLocator.ChatDbcontext.CheckIfTableExists<ChatList>());
}
其中:
- CreateDatabase方法的作用是初始化資料庫,如果在指定的資料庫文件地址中不存在文件,則在訪問資料庫時,SQLite 資料庫引擎會嘗試創建一個新的資料庫文件。這意味著,如果指定的資料庫文件地址沒有文件,EF Core 與 SQLite 的集成會自動創建一個新的資料庫文件。
- CheckTableExists 方法判斷載入的資料庫表是否完整
3.ChatDbcontext初始化和賦值
ChatDbcontext初始化和賦值在MainWindow_Loaded方法中,在首頁載入時,判斷配置中的資料庫文件地址。並載入資料庫。
4.DbContext的使用
如何在程式中使用DbContext來查詢資料庫是重點,下麵是一些應用的場景:
代碼如下:
//數據載入
VMLocator.DataGridViewModel.ChatList=VMLocator.ChatDbcontext.ChatLists.ToObservableCollection();
VMLocator.ChatViewModel.ChatHistory = VMLocator.ChatDbcontext.ChatMessages.ToObservableCollection();
這裡查詢資料庫的記錄賦值給DataGridViewModel和ChatViewModel,實現資料庫的數據的載入。
簡簡單單的兩行代碼,完成了會話列表和聊天記錄的數據載入。
ToObservableCollection擴展
我們需要把資料庫查詢的數據轉換成ObservableCollection的集合做Binding,我們寫一個EF的擴展方法來實現這個轉換。
代碼如下:
/// <summary>
/// 擴展方法
/// </summary>
public static class ObservableCollectionExtensions {
public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> source) {
return new ObservableCollection<T>(source);
}
}
更多的使用方法可以在代碼中查看TerraMours.Chat.Ava
5.生成數據遷移文件
執行Add-Migration 命令
Add-Migration Init0720
由於我們在CreateDatabase代碼里實行了資料庫的更新,所以我們在這裡不需要執行Update-Database 命令
值得註意的是,我們在修改過欄位後,一定要執行Add-Migration 命令生成數據遷移文件,這是資料庫初始化和更新的基礎
6.總結
通過EF core 等ORM框架操作資料庫為我們開發項目時提供了便捷。在不追求極限的速度的前提下,使用EntityFrameWork來做查詢真的很方便。
通過ChatDbcontext來操作資料庫,讓開發變的簡單。希望看完後能給大家帶來幫助。
目前程式還沒有完全開發完成。後續的開發我會及時跟進。閱讀如遇樣式問題,請前往個人博客瀏覽:https://www.raokun.top
目前web端ChatGPT:https://ai.terramours.site
當前開源項目地址:https://github.com/raokun/TerraMours.Chat.Ava