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

新增项目懒加载失效:非代理类异常问题排查与解决咨询

问题描述

维护项目时添加仓库,从数据库获取所有项目数据时,除最后新增的项目外,其余项目均以Castle.Proxies.ProjectProxy形式存在。已配置UseLazyLoadingProxies()并将实体属性标记为virtual启用懒加载,但最新创建的项目无法触发懒加载。

相关代码示例

添加并获取项目的逻辑:

var addedProject = await _projectRepository.AddAsync(projectToAdd);
await _projectRepository.SaveAsync();
var userProjects = await _projectRepository.GetAllAsync()

项目仓库实现:

public class ProjectRepository : Repository<Project>, IProjectRepository
{
    public ProjectRepository(TeamHubDbContext TeamHubDbContext)
        : base(TeamHubDbContext) { }
}

通用仓库抽象类:

public abstract class Repository<TEntity> : IRepository<TEntity>
    where TEntity : class, new()
{
    protected readonly TeamHubDbContext TeamHubDbContext;

    protected Repository(TeamHubDbContext socialNetworkContext)
    {
        TeamHubDbContext = socialNetworkContext;
    }

    public virtual async Task<List<TEntity>> GetAllAsync()
    {
        return await TeamHubDbContext.Set<TEntity>().ToListAsync();
    }

    public async Task<TEntity> AddAsync(TEntity entity)
    {
        return (await TeamHubDbContext.AddAsync(entity)).Entity;
    }


    public virtual async Task SaveAsync()
    {
        await TeamHubDbContext.SaveChangesAsync();
    }
}

DbContext实现:

public partial class TeamHubDbContext : DbContext
{
    public DbSet<Project> Projects { get; set; }

    public TeamHubDbContext(DbContextOptions options)
        : base(options)
    {
        Database.EnsureCreated();
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
    }
}
问题成因
  • 新增实体未被代理包装:调用AddAsync添加的是手动创建的原始实体对象,EF Core不会自动为其生成代理,即使保存到数据库,当前上下文中的该实体依然是原始类型,而非代理类型。
  • 上下文缓存优先加载:调用GetAllAsync时,EF Core会先从ChangeTracker(上下文缓存)中读取已存在的实体。新增的项目因为是缓存中的原始对象,直接被返回;而数据库中已存在的项目是从数据库加载时生成的代理对象,所以显示为Castle.Proxies.ProjectProxy。
解决办法

方法1:保存后重新获取实体

保存后通过主键重新从数据库获取新增项目,确保拿到代理对象:

var addedProject = await _projectRepository.AddAsync(projectToAdd);
await _projectRepository.SaveAsync();
// 假设仓库有根据ID获取的方法
addedProject = await _projectRepository.GetByIdAsync(addedProject.Id);
var userProjects = await _projectRepository.GetAllAsync();

方法2:用上下文创建代理实体

直接通过EF Core的CreateProxy方法生成代理对象再填充属性,从根源保证实体是代理类型:

// 依赖注入获取TeamHubDbContext实例
var projectToAdd = _teamHubDbContext.CreateProxy<Project>();
// 填充项目属性
projectToAdd.Name = "新项目";
projectToAdd.Description = "项目描述";

var addedProject = await _projectRepository.AddAsync(projectToAdd);
await _projectRepository.SaveAsync();
var userProjects = await _projectRepository.GetAllAsync();

方法3:修改AddAsync方法生成代理

在通用仓库的AddAsync方法中,检查并自动为原始实体生成代理:

public async Task<TEntity> AddAsync(TEntity entity)
{
    // 判断当前实体是否为代理对象
    if (!TeamHubDbContext.Entry(entity).IsProxy)
    {
        // 创建代理实例
        var proxyEntity = TeamHubDbContext.CreateProxy<TEntity>();
        // 复制原始实体的属性值到代理对象
        TeamHubDbContext.Entry(proxyEntity).CurrentValues.SetValues(entity);
        entity = proxyEntity;
    }
    return (await TeamHubDbContext.AddAsync(entity)).Entity;
}

方法4:清空上下文缓存(不推荐)

如果不需要保留上下文的追踪状态,可以在获取所有项目前清空ChangeTracker,强制从数据库加载所有代理对象:

var addedProject = await _projectRepository.AddAsync(projectToAdd);
await _projectRepository.SaveAsync();
// 清空上下文所有追踪的实体
TeamHubDbContext.ChangeTracker.Clear();
var userProjects = await _projectRepository.GetAllAsync();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 04:33:16