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

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

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

cs 复制代码
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 服务,同时指定保存日志的数据库文件名。

cs 复制代码
............

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

var app = builder.Build();

............

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

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

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

cs 复制代码
@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 });
    }

}
相关推荐
hqwest1 小时前
C#WPF实战出真汁08--【消费开单】--餐桌面板展示
c#·wpf·ui设计·wpf界面设计
orangapple1 小时前
WPF 打印报告图片大小的自适应(含完整示例与详解)
c#·wpf
异世界贤狼转生码农1 小时前
MongoDB Windows 系统实战手册:从配置到数据处理入门
数据库·mongodb
QuZhengRong2 小时前
【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
android·数据库·excel
码农阿豪2 小时前
Windows从零到一安装KingbaseES数据库及使用ksql工具连接全指南
数据库·windows
时序数据说7 小时前
时序数据库市场前景分析
大数据·数据库·物联网·开源·时序数据库
听雪楼主.11 小时前
Oracle Undo Tablespace 使用率暴涨案例分析
数据库·oracle·架构
我科绝伦(Huanhuan Zhou)11 小时前
KINGBASE集群日常维护管理命令总结
数据库·database
妖灵翎幺11 小时前
Java应届生求职八股(2)---Mysql篇
数据库·mysql
HMBBLOVEPDX11 小时前
MySQL的事务日志:
数据库·mysql