.NET 9.0 的 Blazor Web App 项目、Bootstrap Blazor 组件库、自定义日志 TLog 使用备忘

news/2025/1/31 9:55:57/

一、设计目标:通用、容易修改、使用简单,所有代码保存在一个文件中,方便移植到其他项目使用。

注:示例使用 Bootstrap Blazor 组件库和 EF Core 、Sqlite,需要先使用 Nuget包管理器 添加对应的包。

namespace BlazorWebAppNet9Shared.Services;using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System.ComponentModel.DataAnnotations;/// <summary>
/// 日志记录服务。<br/><br/>
/// 使用示例,第1步:builder.Services.AddTLog("Data Source=SQLiteFileLog.db");<br/>
/// 使用示例,第2步:TLog.Page(UserName, DisplayName, NavigationManager.ToBaseRelativePath(NavigationManager.Uri));
/// </summary>
public static class TLog
{public static TLogDbContext TLogDb { get; set; } = default!;/// <summary>/// 添加 TLog 服务。<br/>/// 示例:builder.Services.AddTLog("Data Source=SQLiteFileLog.db");/// </summary>/// <param name="services"></param>/// <param name="ConnectionString"></param>/// <returns></returns>public static IServiceCollection AddTLog(this IServiceCollection services, string ConnectionString){TLogDb = new TLogDbContext(ConnectionString);// 自动创建数据库和数据表:修改实体定义后,删除原有的数据库自动重新建立;或者根据实体定义手动修改数据库和数据表。TLogDb.Database.EnsureCreated();return services;}public static void Page(string 用户名, string 姓名, string 操作对象){if (TLogDb != null){TLogDb.Add(new TLogEntity() { 操作类型 = TLogOpStyle.浏览, 用户名 = 用户名, 姓名 = 姓名, 操作对象 = 操作对象 });TLogDb.SaveChanges();}}public static void Create(string 用户名, string 姓名, string 操作对象, string? 操作说明, bool 操作结果){if (TLogDb != null){TLogDb.Add(new TLogEntity() { 操作类型 = TLogOpStyle.新建, 用户名 = 用户名, 姓名 = 姓名, 操作对象 = 操作对象, 操作说明 = 操作说明, 操作结果 = 操作结果 });TLogDb.SaveChanges();}}public static void Delete(string 用户名, string 姓名, string 操作对象, string? 操作说明, bool 操作结果){if (TLogDb != null){TLogDb.Add(new TLogEntity() { 操作类型 = TLogOpStyle.删除, 用户名 = 用户名, 姓名 = 姓名, 操作对象 = 操作对象, 操作说明 = 操作说明, 操作结果 = 操作结果 });TLogDb.SaveChanges();}}public static void Update(string 用户名, string 姓名, string 操作对象, string? 操作说明, bool 操作结果){if (TLogDb != null){TLogDb.Add(new TLogEntity() { 操作类型 = TLogOpStyle.编辑, 用户名 = 用户名, 姓名 = 姓名, 操作对象 = 操作对象, 操作说明 = 操作说明, 操作结果 = 操作结果 });TLogDb.SaveChanges();}}public static void Read(string 用户名, string 姓名, string 操作对象, string? 操作说明, bool 操作结果){if (TLogDb != null){TLogDb.Add(new TLogEntity() { 操作类型 = TLogOpStyle.查询, 用户名 = 用户名, 姓名 = 姓名, 操作对象 = 操作对象, 操作说明 = 操作说明, 操作结果 = 操作结果 });TLogDb.SaveChanges();}}}/// <summary>
/// 日志数据库上下文:建立使用独立数据库,与业务数据分开存放。
/// </summary>
/// <param name="ConnectionString"></param>
public class TLogDbContext(string ConnectionString) : DbContext
{public DbSet<TLogEntity> TLogEntitys { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){base.OnConfiguring(optionsBuilder);optionsBuilder.UseSqlite(ConnectionString);}/* 建立索引:建立在实体定义时使用 Index 注解 建立,更方便。protected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.Entity<TLogEntity>().HasIndex(t => new { t.用户名, t.姓名, t.操作类型, t.操作对象 });modelBuilder.Entity<TLogEntity>().HasIndex(t => new { t.用户名 });}*/
}/// <summary>
/// 日志实体:后续可以根据需要增加,注意不要编辑、删除已有属性。
/// </summary>
[Index(nameof(Id))]
[Index(nameof(时间))]
[Index(nameof(用户名))]
[Index(nameof(姓名))]
[Index(nameof(操作类型))]
[Index(nameof(操作对象))]
[Index(nameof(姓名), nameof(操作对象))]
public class TLogEntity
{[Key]public long Id { get; set; }public DateTime 时间 { get; set; } = DateTime.Now;public required string 用户名 { get; set; }public required string 姓名 { get; set; }public TLogOpStyle 操作类型 { get; set; } = TLogOpStyle.浏览;public required string 操作对象 { get; set; }public string? 操作说明 { get; set; }public bool 操作结果 { get; set; } = true;}/// <summary>
/// 日志类型:后续可以根据需要增加,注意不要编辑、删除已有类型。
/// </summary>
public enum TLogOpStyle
{/// <summary>/// 用于记录访问路径:Page/// </summary>浏览,/// <summary>/// 增删改查CRUD:Create/// </summary>新建,/// <summary>/// 增删改查CRUD:Read/// </summary>查询,/// <summary>/// 增删改查CRUD:Update/// </summary>编辑,/// <summary>/// 增删改查CRUD:Delete/// </summary>删除,}

代码文件:TLog.cs 

二、使用步骤

1.  在 Program.cs 中添加 TLog 服务,同时指定保存日志的数据库文件名。

............builder.Services.AddTLog("Data Source=SQLiteFileLog.db");var app = builder.Build();............

2. 在需要记录日志的位置,直接使用 TLog.Page 、TLog.Create 等静态方法进行记录,不需要进行注入、New等操作,简化代码输入。

    @inject NavigationManager NavigationManager;protected override void OnInitialized(){base.OnInitialized();// 记录日志TLog.Page(UserName, DisplayName, NavigationManager.ToBaseRelativePath(NavigationManager.Uri));}

3. 使用 TLogManager.razor 组件浏览日志

@page "/Log/TLogManager"<Table TItem="TLogEntity" OnQueryAsync="@OnQueryAsync"AutoGenerateColumns=true HeaderStyle="TableHeaderStyle.Light"ClickToSelect="true" ShowLoading="true" AllowResizing="true"IsPagination="true" PageItemsSource="new int[] { 10, 20, 30, 60, 100 }"ShowToolbar="true" ShowDefaultButtons="false">
</Table>@code {[CascadingParameter]public LayoutBB.MainLayout? mainLayout { get; set; }@inject NavigationManager NavigationManager;protected override void OnInitialized(){base.OnInitialized();// 记录日志TLog.Page(mainLayout?.UserName ?? "", mainLayout?.DisplayName ?? "", NavigationManager.ToBaseRelativePath(NavigationManager.Uri));}private async Task<QueryData<TLogEntity>> OnQueryAsync(QueryPageOptions options){IEnumerable<TLogEntity> items = TLog.TLogDb.TLogEntitys.OrderByDescending(t => t.时间).ToList();var total = items.Count();items = items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList();return await Task.FromResult(new QueryData<TLogEntity>() { Items = items, TotalCount = total, IsSorted = true, IsFiltered = true, IsSearch = true });}}


http://www.ppmy.cn/news/1568122.html

相关文章

每日 Java 面试题分享【第 16 天】

欢迎来到每日 Java 面试题分享栏目&#xff01; 订阅专栏&#xff0c;不错过每一天的练习 今日分享 3 道面试题目&#xff01; 评论区复述一遍印象更深刻噢~ 目录 问题一&#xff1a;Java 运行时异常和编译时异常之间的区别是什么&#xff1f;问题二&#xff1a;什么是 Jav…

Pyecharts之地图图表的强大功能

在数据可视化领域中&#xff0c;地图图表是一种强大的工具&#xff0c;能够直观地展现与地理位置相关的数据信息&#xff0c;帮助我们更好地洞察数据的地域特征和分布规律。Pyecharts 为我们提供了丰富的地图图表功能&#xff0c;让我们可以轻松实现各种地理信息的可视化展示。…

数据结构初阶之双向链表的介绍与双向链表的实现

一、概念与结构 带头双向循环链表 next &#xff1a;指向下一个结点&#xff08;后继结点&#xff09; prev &#xff1a;指向前一个结点&#xff08;前驱结点&#xff09; 二、实现双向链表 项目创建的时候&#xff0c;要创建一个头文件&#xff08;.h&#xff09;List.h …

现代 linux 里一个进程允许打开几个文件:答案是 1024 或者更多

&#xff08;1&#xff09; 测试一下&#xff1a; &#xff08;2&#xff09; 谢谢

【新人系列】Python 入门(二十九):常用标准库 - 下

✍ 个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4dd; 专栏地址&#xff1a;https://blog.csdn.net/newin2020/category_12801353.html &#x1f4e3; 专栏定位&#xff1a;为 0 基础刚入门 Python 的小伙伴提供详细的讲解&#xff0c;也欢迎大佬们…

[STM32 标准库]定时器输出PWM配置流程 PWM模式解析

前言&#xff1a; 本文内容基本来自江协&#xff0c;整理起来方便日后开发使用。MCU&#xff1a;STM32F103C8T6。 一、配置流程 1、开启GPIO&#xff0c;TIM的时钟 /*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟RCC_APB2PeriphClockC…

BWM 世界模型

DGX AGX Ominiverse With Cosmos 功能 1w 张 H100 训练了 3个月 使用 Ray 串流 数据 数据准备 处理 pipeline 数组组成 真实世界的物理数据 训练 1、使用 L1 损失&#xff0c;最小化 输入和重构视频之间的像素级差异 以及基于 VGG19 的一个特征感知损失 2、使用光流的损…

独立成分分析 (ICA):用于信号分离或降维

独立成分分析 (Independent Component Analysis, ICA) 是一种用于信号分离和降维的统计方法&#xff0c;常用于盲源分离 (Blind Source Separation, BSS) 问题&#xff0c;例如音频信号分离或脑电信号 (EEG) 处理。 实现 ICA&#xff08;独立成分分析&#xff09; 步骤 生成…