本篇部落格是我的開源專案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的實現。
<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>
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;
}
}
其中包括:
VMLocator類中,建立一個靜態欄位來儲存 DbContext 的範例
程式碼如下:
private static ChatDbcontext _chatDbcontext;
public static ChatDbcontext ChatDbcontext {
get => (_chatDbcontext ??= new ChatDbcontext());
set => _chatDbcontext = value;
}
程式碼如下:
/// <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>());
}
其中:
ChatDbcontext初始化和賦值在MainWindow_Loaded方法中,在首頁載入時,判斷設定中的資料庫檔案地址。並載入資料庫。
如何在程式中使用DbContext來查詢資料庫是重點,下面是一些應用的場景:
程式碼如下:
//資料載入
VMLocator.DataGridViewModel.ChatList=VMLocator.ChatDbcontext.ChatLists.ToObservableCollection();
VMLocator.ChatViewModel.ChatHistory = VMLocator.ChatDbcontext.ChatMessages.ToObservableCollection();
這裡查詢資料庫的記錄賦值給DataGridViewModel和ChatViewModel,實現資料庫的資料的載入。
簡簡單單的兩行程式碼,完成了對談列表和聊天記錄的資料載入。
我們需要把資料庫查詢的資料轉換成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
執行Add-Migration 命令
Add-Migration Init0720
由於我們在CreateDatabase程式碼裡實行了資料庫的更新,所以我們在這裡不需要執行Update-Database 命令
值得注意的是,我們在修改過欄位後,一定要執行Add-Migration 命令生成資料遷移檔案,這是資料庫初始化和更新的基礎
通過EF core 等ORM框架運算元據庫為我們開發專案時提供了便捷。在不追求極限的速度的前提下,使用EntityFrameWork來做查詢真的很方便。
通過ChatDbcontext來運算元據庫,讓開發變的簡單。希望看完後能給大家帶來幫助。
目前程式還沒有完全開發完成。後續的開發我會及時跟進。閱讀如遇樣式問題,請前往個人部落格瀏覽:https://www.raokun.top
目前web端ChatGPT:https://ai.terramours.site
當前開源專案地址:https://github.com/raokun/TerraMours.Chat.Ava