在C# WebCore Entity Framework中如何获取其他实体?
嘿,我刚好做过类似的文件缓存转正的场景,给你梳理下具体的实现方案和代码示例,应该能帮到你:
核心思路
先明确整个流程的核心逻辑:用户上传文件后暂存到FileCacheContext作为缓存,待用户确认操作后,将缓存文件的元数据(甚至文件内容)迁移到正式的业务数据库表中,同时清理缓存记录(或标记为已迁移)。关键要保证迁移过程的原子性,避免数据不一致。
具体实现步骤
1. 实体定义
首先确保缓存表和正式业务表的实体有对应的属性,方便后续映射:
// 缓存表实体 - 存储暂存的文件信息 public class FileCache { public Guid Id { get; set; } public string FileName { get; set; } public string FileHash { get; set; } // 用于校验文件完整性,上传时生成 public long ContentLength { get; set; } public byte[] FileContent { get; set; } // 如果是小文件可以存数据库,大文件建议存路径 public Guid UploaderUserId { get; set; } // 记录上传用户,用于权限校验 public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } // 正式业务表实体 - 存储用户确认后的文件 public class UserUploadedFile { public Guid Id { get; set; } public string FileName { get; set; } public string FileHash { get; set; } public long ContentLength { get; set; } public byte[] FileContent { get; set; } public Guid UserId { get; set; } public DateTime ConfirmedAt { get; set; } = DateTime.UtcNow; // 可以添加更多业务相关字段,比如关联的业务ID等 }
2. 确保上下文注入正确
你已经在启动时注入了FileCacheContext,记得把正式业务的上下文也注册进去(如果还没的话):
// Program.cs builder.Services.AddDbContext<FileCacheContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("FileCacheConn"))); builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("AppMainConn")));
3. 实现文件升级的API接口
写一个REST接口,处理用户的确认请求,这里要注意用事务保证操作的原子性:
[ApiController] [Route("api/file-operations")] public class FileOperationController : ControllerBase { private readonly FileCacheContext _cacheDb; private readonly AppDbContext _mainDb; public FileOperationController(FileCacheContext cacheDb, AppDbContext mainDb) { _cacheDb = cacheDb; _mainDb = mainDb; } [HttpPost("upgrade/{cacheFileId:guid}")] public async Task<IActionResult> UpgradeCachedFile(Guid cacheFileId) { // 先获取当前用户ID(根据你的身份验证方式调整,比如JWT) var currentUserId = User.FindFirstValue(ClaimTypes.NameIdentifier); if (string.IsNullOrEmpty(currentUserId)) { return Unauthorized("请先登录"); } // 1. 查询缓存文件,同时校验权限 var cachedFile = await _cacheDb.FileCaches .FirstOrDefaultAsync(f => f.Id == cacheFileId && f.UploaderUserId == Guid.Parse(currentUserId)); if (cachedFile == null) { return NotFound("缓存文件不存在或您无权限操作"); } // 2. 开启事务(如果两个上下文用的是同一个数据库,用单个事务即可;不同库则用分布式事务) using var transaction = await _mainDb.Database.BeginTransactionAsync(); try { // 3. 映射缓存文件到正式实体 var officialFile = new UserUploadedFile { Id = Guid.NewGuid(), FileName = cachedFile.FileName, FileHash = cachedFile.FileHash, ContentLength = cachedFile.ContentLength, FileContent = cachedFile.FileContent, UserId = Guid.Parse(currentUserId) }; // 4. 添加到正式数据库 _mainDb.UserUploadedFiles.Add(officialFile); await _mainDb.SaveChangesAsync(); // 5. 清理缓存(或者标记为已迁移,根据需求保留历史) _cacheDb.FileCaches.Remove(cachedFile); await _cacheDb.SaveChangesAsync(); // 6. 提交事务 await transaction.CommitAsync(); // 返回正式文件信息给前端 return Ok(new { FileId = officialFile.Id, officialFile.FileName, officialFile.ConfirmedAt, Message = "文件已成功升级" }); } catch (Exception ex) { // 出错回滚事务 await transaction.RollbackAsync(); return StatusCode(500, $"文件升级失败:{ex.Message}"); } } }
关键注意事项
- 事务处理:如果缓存库和业务库是同一个数据库,直接用单个上下文的事务就行;如果是不同数据库,需要启用EF Core的分布式事务支持(比如依赖
Microsoft.EntityFrameworkCore.SqlServer的分布式事务功能)。 - 大文件优化:如果上传的是大文件,不要把文件内容存在数据库里,建议存储到本地磁盘或云存储,数据库只存文件路径和元数据,迁移时只需要复制路径或者修改标记,性能会好很多。
- 缓存清理:要定时清理未被确认的缓存文件,避免数据库膨胀。可以用ASP.NET Core的
HostedService写一个后台任务,定期删除创建时间超过N小时的缓存记录。 - 完整性校验:迁移时可以重新计算文件的Hash值,和缓存中的Hash对比,确保文件在缓存期间没有被篡改。
- 权限控制:一定要校验用户是否有权限操作对应的缓存文件,避免越权操作。
内容的提问来源于stack exchange,提问作者antonye
相关产品推荐
相关产品推荐

