You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用.NET Core 2.0和Entity Framework编程式保存对象到SQL Server

刚上手.NET Core 2.0 MVC的时候,我要做一个自定义事件日志功能——既要能编程式记录事件/对象,还要支持管理员查看,踩了好几个坑才搞定。下面是我亲测可行的完整方案,分享给同阶段的朋友:

自定义事件日志实现全流程

1. 项目初始化

首先创建带独立用户账户的ASP.NET Core Web应用(MVC模板),这个模板自带Identity身份验证体系,刚好能帮我们快速实现管理员权限控制,省了不少重复造轮子的工作。

2. 创建日志数据模型

在Models文件夹下新建CustomErrorLogModel.cs,用来存储日志的核心信息,字段可以根据你的需求调整:

using System;
using System.ComponentModel.DataAnnotations;

namespace YourProjectName.Models
{
    public class CustomErrorLogModel
    {
        [Key]
        public int LogId { get; set; }
        
        // 日志级别:Error/Warning/Info,用字符串或枚举都行
        [Required]
        public string LogLevel { get; set; }
        
        // 日志简短标题,方便快速识别
        [Required]
        public string Title { get; set; }
        
        // 日志详细内容,比如异常堆栈、操作详情
        public string Details { get; set; }
        
        // 日志生成时间,默认取UTC时间
        public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
        
        // 关联操作人ID(可选,需要记录谁触发的事件时用)
        public string UserId { get; set; }
        
        // 关联Identity用户表,方便查询操作人信息
        public virtual ApplicationUser User { get; set; }
    }
}

3. 配置EF Core数据库上下文

要让EF Core识别这个日志模型,需要在ApplicationDbContext.cs里添加对应的DbSet:

public DbSet<CustomErrorLogModel> CustomErrorLogs { get; set; }

然后打开Package Manager Console执行迁移命令,把日志表同步到数据库:

Add-Migration AddCustomErrorLogsTable
Update-Database

4. 封装日志服务(核心步骤)

为了方便在项目各处调用日志功能,最好封装成独立服务,避免重复代码。

第一步:定义服务接口

在Services文件夹下新建ICustomLogService.cs:

using YourProjectName.Models;

namespace YourProjectName.Services
{
    public interface ICustomLogService
    {
        // 同步方法,也可以改成异步提升性能
        void LogEvent(string logLevel, string title, string details = null, string userId = null);
    }
}

第二步:实现服务逻辑

接着新建CustomLogService.cs,实现接口的日志保存逻辑:

using Microsoft.EntityFrameworkCore;
using YourProjectName.Data;
using YourProjectName.Models;

namespace YourProjectName.Services
{
    public class CustomLogService : ICustomLogService
    {
        private readonly ApplicationDbContext _dbContext;

        // 构造函数注入DbContext
        public CustomLogService(ApplicationDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public void LogEvent(string logLevel, string title, string details = null, string userId = null)
        {
            var logEntry = new CustomErrorLogModel
            {
                LogLevel = logLevel,
                Title = title,
                Details = details,
                UserId = userId
            };

            _dbContext.CustomErrorLogs.Add(logEntry);
            _dbContext.SaveChanges();
        }
    }
}

第三步:注册服务到DI容器

在Startup.cs的ConfigureServices方法里添加服务注册:

services.AddScoped<ICustomLogService, CustomLogService>();

5. 实现管理员日志查看功能

新建日志控制器

在Controllers文件夹下创建LogsController.cs,用[Authorize(Roles = "Admin")]限制只有管理员角色能访问:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using YourProjectName.Data;
using YourProjectName.Models;

namespace YourProjectName.Controllers
{
    [Authorize(Roles = "Admin")]
    public class LogsController : Controller
    {
        private readonly ApplicationDbContext _dbContext;

        public LogsController(ApplicationDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        // 日志列表页
        public async Task<IActionResult> Index()
        {
            // 按时间倒序查询,关联用户表获取操作人名称
            var logs = await _dbContext.CustomErrorLogs
                .Include(l => l.User)
                .OrderByDescending(l => l.CreatedAt)
                .ToListAsync();
            return View(logs);
        }

        // 日志详情页
        public async Task<IActionResult> Details(int? id)
        {
            if (id == null) return NotFound();

            var log = await _dbContext.CustomErrorLogs
                .Include(l => l.User)
                .FirstOrDefaultAsync(m => m.LogId == id);
            if (log == null) return NotFound();

            return View(log);
        }
    }
}

创建对应的视图

在Views文件夹下新建Logs目录,然后创建两个视图:

Index.cshtml(日志列表)

@model IEnumerable<YourProjectName.Models.CustomErrorLogModel>

@{
    ViewData["Title"] = "系统事件日志";
}

<h1>系统事件日志</h1>

<table class="table table-striped">
    <thead>
        <tr>
            <th>日志级别</th>
            <th>标题</th>
            <th>发生时间</th>
            <th>操作人</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody>
@foreach (var log in Model) {
        <tr>
            <td>@log.LogLevel</td>
            <td>@log.Title</td>
            <td>@log.CreatedAt.ToLocalTime()</td>
            <td>@log.User?.UserName</td>
            <td><a asp-action="Details" asp-route-id="@log.LogId">查看详情</a></td>
        </tr>
}
    </tbody>
</table>

Details.cshtml(日志详情)

@model YourProjectName.Models.CustomErrorLogModel

@{
    ViewData["Title"] = "日志详情";
}

<h1>日志详情</h1>

<div class="card">
    <div class="card-body">
        <dl class="row">
            <dt class="col-sm-3">日志级别</dt>
            <dd class="col-sm-9">@Model.LogLevel</dd>
            
            <dt class="col-sm-3">标题</dt>
            <dd class="col-sm-9">@Model.Title</dd>
            
            <dt class="col-sm-3">发生时间</dt>
            <dd class="col-sm-9">@Model.CreatedAt.ToLocalTime()</dd>
            
            <dt class="col-sm-3">操作人</dt>
            <dd class="col-sm-9">@Model.User?.UserName</dd>
            
            <dt class="col-sm-3">详细内容</dt>
            <dd class="col-sm-9">@Model.Details</dd>
        </dl>
    </div>
</div>

<a asp-action="Index" class="btn btn-secondary mt-3">返回列表</a>

6. 编程式调用日志服务

现在可以在任何需要记录日志的地方,通过依赖注入调用ICustomLogService,比如在控制器里:

using Microsoft.AspNetCore.Mvc;
using YourProjectName.Services;

namespace YourProjectName.Controllers
{
    public class HomeController : Controller
    {
        private readonly ICustomLogService _logService;

        public HomeController(ICustomLogService logService)
        {
            _logService = logService;
        }

        public IActionResult Index()
        {
            // 记录普通操作日志
            _logService.LogEvent("Info", "用户访问首页", $"访问IP:{HttpContext.Connection.RemoteIpAddress}", User.Identity.Name);
            
            // 异常场景日志记录
            try
            {
                // 你的业务逻辑代码
            }
            catch (Exception ex)
            {
                _logService.LogEvent("Error", "首页加载失败", $"异常信息:{ex.Message}\n堆栈:{ex.StackTrace}", User.Identity.Name);
            }
            
            return View();
        }
    }
}

额外优化建议

  • 异步保存日志:把LogEvent改成异步方法async Task LogEventAsync(...),避免阻塞主线程;
  • 使用枚举定义日志级别:代替字符串,减少拼写错误;
  • 添加分页与筛选:日志多了之后,在列表页添加分页、按级别/时间范围筛选功能;
  • 管理员角色配置:确保你已经通过Identity创建了Admin角色,并分配给对应的用户。

内容的提问来源于stack exchange,提问作者user6383418

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 06:23:20