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创建模板项目-基础可跳转:

创建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;
} }

其中包括:

  1. OnConfiguring 根据配置文件中的数据库地址设置数据库连接
  2. OnModelCreating 中设置实体类的主键
  3. ChangeConnection 方法实现切换数据库连接
  4. 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>());
}

其中:

  1. CreateDatabase方法的作用是初始化数据库,如果在指定的数据库文件地址中不存在文件,则在访问数据库时,SQLite 数据库引擎会尝试创建一个新的数据库文件。这意味着,如果指定的数据库文件地址没有文件,EF Core 与 SQLite 的集成会自动创建一个新的数据库文件。
  2. CheckTableExists 方法判断加载的数据库表是否完整

3.ChatDbcontext初始化和赋值

ChatDbcontext初始化和赋值在MainWindow_Loaded方法中,在首页加载时,判断配置中的数据库文件地址。并加载数据库。

4.DbContext的使用

如何在程序中使用DbContext来查询数据库是重点,下面是一些应用的场景:

代码如下:

//数据加载
VMLocator.DataGridViewModel.ChatList=VMLocator.ChatDbcontext.ChatLists.ToObservableCollection();
VMLocator.ChatViewModel.ChatHistory = VMLocator.ChatDbcontext.ChatMessages.ToObservableCollection();

这里查询数据库的记录赋值给DataGridViewModelChatViewModel,实现数据库的数据的加载。

简简单单的两行代码,完成了会话列表和聊天记录的数据加载。

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

Avalonia 使用EFCore调用SQLite实现Singleton全局注册的更多相关文章

  1. vux 全局注册组件

    背景:调试better-scroll的时候进行封装,作为组件来调用: 希望:全局注册组件: 1,在src的main.js下: 这样就可以用了:

  2. RT/Metro商店应用如何调用SQLite数据库

    RT/Metro商店应用如何调用SQLite数据库 使用前,要安装:SQLite for Windows Runtime (Windows 8.1)(一个VS插件).还有Visual C++ Runt ...

  3. C#调用SQLite报错:无法加载 DLL“SQLite.Interop.dll”: 找不到指定的模块

    C#调用SQLite数据库,有些情况下会报以下这个错误: 无法加载 DLL“SQLite.Interop.dll”: 找不到指定的模块 实际上程序目录中是存在SQLite.Interop.dll这个文 ...

  4. 关于.NET C#调用Sqlite的总结二

    关于.NET C#调用Sqlite的总结一 在上一篇中我一直疑惑为什么我在使用多层架构进行开发时总是会报些莫名的错误,难道要使用Sqlite就不能分层吗?只能将UI.业务逻辑.数据访问统统都要写在一层 ...

  5. 关于.NET C#调用Sqlite的总结一

    --前记 由于自己的密码太多又不容易记住,经常性的会忘记.所以想找个管理软件管理下,可用网上下载的担心不安全.于是自己开始动手写个属于自己的密码管理软件. 因为自己一直做的是WEB开发,对WPF懂的不 ...

  6. 生命周期函数以及vue的全局注册

    beforeCreate 在创造实例之前 created 创造实例以后 beforeMount 在挂载前 render 渲染节点到页面上 //将虚拟dom数组渲染出来 mounted 挂载以后 bef ...

  7. vue组件局部与全局注册的区别

    //局部注册 var mycomponent = new extend({        <!--Vue.extend()是Vue构造器的扩展,调用Vue.extend()我们将创建一个组件构造 ...

  8. vue 组件 全局注册和局部注册

    全局注册,注册的组件需要在初始化根实例之前注册了组件: 局部注册,通过使用组件实例选项注册,可以使组件仅在另一个组件或者实例的作用域中可用: 全局组件 js Vue.component('tab-ti ...

  9. vue_全局注册过滤器

    在一个项目中, 某些过滤器全局都有可能用的到, 统一管理并自动化全局注册是很方便的. 代码如下, 后续只需要在src/filters/index.js中添加方法就可以全局使用过滤器了. // src/ ...

  10. Vue 全局注册逐渐 和 局部注册组件

    //定义一个名为 button-counter 的新组件 Script: Vue.component('button-counter',{//button-counter 这个是组件的名字 data: ...

随机推荐

  1. 苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!

    开心一刻 2023年元旦,我妈又开始了对我的念叨 妈:你到底想多少岁结婚 我:60 妈:60,你想找个多大的 我:找个55的啊,她55我60,结婚都有退休金,不用上班不用生孩子,不用买车买房,成天就是 ...

  2. 基于pip的python包管理工具

    以下是软件下载链接:https://mysecreat.lanzoub.com/i5yvf0swgtne 软件功能:可以对python包进行安装.卸载.升级.换源等操作,不用输入复杂命令 源码: im ...

  3. Comparator之用最少数量的箭引爆气球

    文章目录 前言 关于Comparator 原题 前言 今天刷个题,遇到一个很有趣的问题,关于Comparator的使用,感觉也是一个关于写代码的一些小细节的问题 关于Comparator Compar ...

  4. 2023-04-26:给定一个数组componets,长度为A, componets[i] = j,代表i类型的任务需要耗时j 给定一个二维数组orders,长度为M, orders[i][0]代表i

    2023-04-26:给定一个数组componets,长度为A, componets[i] = j,代表i类型的任务需要耗时j 给定一个二维数组orders,长度为M, orders[i][0]代表i ...

  5. 2022-12-23:portainer是docker的web可视化工具。如果根据docker部署去写yaml,默认local是k8s,而不是docker,这不符合需求,需要修改yaml。请问部署在

    2022-12-23:portainer是docker的web可视化工具.如果根据docker部署去写yaml,默认local是k8s,而不是docker,这不符合需求,需要修改yaml.请问部署在 ...

  6. 2022-10-04:以下go语言代码输出什么?A:{123} main.T{x:123} B:{123} T{x:123} C:boo boo D:boo main.T{x:123}。 packag

    2022-10-04:以下go语言代码输出什么?A:{123} main.T{x:123} B:{123} T{x:123} C:boo boo D:boo main.T{x:123}. packag ...

  7. sql server 系统表详细说明

    sql server 系统表详细说明 sysaltfiles 主数据库 保存数据库的文件syscharsets 主数据库字符集与排序顺序sysconfigures 主数据库 配置选项 syscurco ...

  8. js代理(Proxy) 和 反射(Reflection)

    在实际开发中经常会遇到js抛出的错误,但是我们有没有想过自己去接管js异常验证,根据自己的需求抛出异常呢?原本也许不行,但是在es6出来后就可以做到了 一.代理(Proxy) 什么是'代理' 呢?代理 ...

  9. web自动化08-下拉选择框、弹出框、滚动条

    1.下拉选择框操作 下拉框就是HTML中<select>元素:   先列需求: 需求:使用'注册A.html'页面,完成对城市的下拉框的操作 1).选择'广州' 2).暂停2秒,选择'上海 ...

  10. Redis系列14:使用List实现消息队列

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 Redis系列4:高可用之Sentinel(哨兵模式) Redis系列5: ...