当前位置: 首页 > article >正文

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

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

注:示例使用 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.kler.cn/a/517552.html

相关文章:

  • 【开源免费】基于Vue和SpringBoot的景区民宿预约系统(附论文)
  • Pyecharts之饼图与多饼图的应用
  • C++11新特性之auto与decltype(总结)
  • 22_解析XML配置文件_List列表
  • 总线、UART、IIC、SPI
  • 【github 使用相关】提交pr和commit message Conventional Commits 规范 代码提交的描述该写什么?
  • 【开源实录】从App Store审核失败到开源:一个AI辅助开发的SwiftUI项目
  • Docker 在Linux 系统中的使用说明
  • 数据结构与算法再探(六)动态规划
  • AIP-128 声明友好接口
  • Java语言程序设计(第3版) 课后练习
  • 《jEasyUI 动态改变列》
  • 解决lombok注解失效
  • 鸿蒙(HarmonyOS) HDC 命令合集分类记录
  • UDP/TCP ③-拥塞控制 || 滑动窗口 || 流量控制 || 快速重传
  • FineBI数据连接失败
  • 提示词工程(Prompt Engineering)
  • Android多语言开发自动化生成工具
  • Unity3D仿星露谷物语开发25之创建时钟界面
  • 【Rust自学】14.6. 安装二进制crate
  • 「 机器人 」利用数据驱动模型替代仿真器:加速策略训练并降低硬件依赖
  • CDSN 2024博客之星总评选-主题文章创作,我的AI之路-起手篇
  • 青少年CTF练习平台 PHP的XXE
  • 【深度学习|迁移学习】渐进式学习策略 (Progressive Learning Strategy)详述(一)
  • vulnhub 靶场 —— MrRobot
  • 星火大模型接入及文本生成HTTP流式、非流式接口(JAVA)