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

Entity Framework Core搭配SQLite时延迟加载失效问题求助

问题:Supply类中Employee属性为空,导致EmployeeName报错

我拥有Delivery类与Employee类,为方便将数据加载到DataGridView,给Supply类创建了EmployeeName属性以返回员工姓名(替代员工ID),但运行时Employee属性为空引发报错。已在DbContext配置中启用延迟加载代理,使用SQLite数据库,理论上功能应正常,但实际未生效。

Supply类代码

public partial class Supply : EntityBase
{
    [Browsable(false)]
    public override int Id { get; set; }
    [DisplayName("Дата поставки")]
    public string Date { get; set; } = null!;
    [Browsable(false)]
    public int EmployeeId { get; set; }
    [Browsable(false)]
    public virtual Employee Employee { get; set; } = null!;
    [Browsable(false)]
    public virtual ICollection<Product> Products { get; set; } = new List<Product>();

    [NotMapped]
    [DisplayName("Работник")]
    public string EmployeeName 
    {
        get
        {
            using(var context = new IssuingOrdersDbContext())
            {
                var item = context.Supplies.First(i=>i.Id==Id);
                return item.Employee.FullName;
            }
        }
    }
}

DbContext配置代码

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
    .UseLazyLoadingProxies()
    .UseSqlite("Data Source=D:\\СГАЭК\\БДиСУБД\\Сем2\\Курсовая\\IssuingOrdersDB.db");

解决方案

问题根源

  1. 延迟加载未触发:在EmployeeName的getter中新建了独立的DbContext实例,这个上下文查询出的Supply对象没有被延迟加载代理包装,无法自动加载关联的Employee。
  2. 重复查询性能问题:每次获取EmployeeName都发起一次数据库查询,效率极低,还容易引发上下文状态冲突。

修复步骤

方案1:显式加载关联数据(推荐)

在查询Supplies时,主动Include关联的Employee数据,确保加载时就获取到员工信息:

// 获取Supply列表时添加Include
using (var context = new IssuingOrdersDbContext())
{
    var supplies = context.Supplies.Include(s => s.Employee).ToList();
    // 将supplies绑定到DataGridView
    dataGridView1.DataSource = supplies;
}

然后修改EmployeeName属性,无需再新建上下文:

[NotMapped]
[DisplayName("Работник")]
public string EmployeeName 
{
    get => Employee?.FullName ?? "未指定员工";
}

方案2:确保延迟加载正常工作(不推荐用于UI场景)

如果坚持使用延迟加载,需满足以下条件:

  • 实体类为public非密封(你的Supply是partial,符合要求)
  • 导航属性必须是virtual(Employee属性已满足)
  • 必须使用加载实体的原始DbContext,不能在getter中新建上下文。但这种方式会导致DataGridView每次渲染行都触发一次数据库查询,性能很差,不建议使用。

方案3:投影查询直接获取所需数据

可以直接在查询时投影出包含员工姓名的匿名类型,避免处理实体关联:

using (var context = new IssuingOrdersDbContext())
{
    var supplyData = context.Supplies
        .Select(s => new 
        {
            s.Id,
            s.Date,
            Работник = s.Employee.FullName
        })
        .ToList();
    dataGridView1.DataSource = supplyData;
}

这种方式无需修改Supply类,直接获取绑定所需的数据。


内容的提问来源于stack exchange,提问作者Quasarka N.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:55:14