EF Core:Class,属性 包含列表,returns 列表为 null,在获取 DbSet 时

EF Core: Class with property containing List, returns the list as null, when fetching the DbSet

我有一个包含 class“周”的 DbSet。 class 中的属性之一是包含 class“日”的列表。

public class Week
{
    [Key]
    public int Id { get; set; }
    public List<Day> Days { get; set; }
    public bool Ferie { get; set; }
    public int WeekNo { get; set; }
    public int Year { get; set; }
}

public class Day
{
    [Key]
    public int Id { get; set; }
    public List<ProjectTask> Tasks { get; set; }
    public DateTime Date { get; set; }
    public int AvailableHours { get; set; }
    public int HoursLeftToBook { get; set; }
    public string? DayName { get; set; }
    public int Priority { get; set; }
}

数据库设置如下,迁移。我在更改后创建了一个新闻迁移,所以数据库应该是最新的。

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
        Database.Migrate();
    }

    public DbSet<Week> Weeks { get; set; }
}

目前,我正在从控制器测试数据库。首先,我加载模拟数据,将其保存到数据库中,然后再次从数据库中加载数据,以显示在页面上。

    public IActionResult Index()
    {
        PlannerViewModel plannerViewModel = new();
        
        var mock = _plannerService.MockData();
        
        // Save to database
        _dataService.SaveWeeks(_plannerService.AssignProjects(mock));

        // Get from database
        plannerViewModel.Weeks = _dataService.GetWeeks();

        return View(plannerViewModel);
    }

table的保存和返回方法,供参考:

    public void SaveWeeks(List<Week> weeks)
    {
        _db.Weeks.AddRange(weeks);
        _db.SaveChanges();
    }

    public List<Week> GetWeeks()
    {
        return _db.Weeks.ToList();
    }

加载时页面上的星期显示正常,并且包含正确的日期。之后我注释掉获取模拟数据并将其保存到数据库的行,因为模拟数据已经添加。只是行“_dataService.GetWeeks();”保留(当然还有 viewModel 代码),然后重新运行项目。现在仍然可以正确地从数据库中获取周数,但突然间每周的天数列表为空。我检查了数据库,两次运行之间没有任何变化。这些关系是否连接不正确?如果是这样,为什么它会在第一次工作,而不是以下?

可能是你获取数据的方式没有急于加载相关数据.Include。当您调用将实体添加到 DbContext 的数据时,该 DbContext 将跟踪那些新添加的实体以及与它们一起添加的任何相关实体。当您从 DbContext 读取顶级实体(周)时,即使您没有急切地加载子实体(天),由于 DbContext 已经在跟踪天数,它仍然会填充这些子关系。

你第二次依赖数据库中已有的数据。 DbContext 没有 跟踪这些实体,因此当您获得 dbContext.Weeks.ToList() 时,您将只获得周数,没有关联的天数。

每当您在获取对象图时需要相关数据时,请确保:

A) 始终预加载相关数据:

var weeks = dbContext.Weeks.Include(w => w.Days).ToList();

B) 依靠投影在不需要实体的地方获取所需的数据:

var weekDetails = dbContext.Weeks
    .Select(w => new WeekDetailViewModel
    {
        Id = w.Id,
        WeekNo = w.WeekNo,
        Days = w.Days.Select(d => new DayDetailViewModel
        {
            Id = d.Id,
            // ...
        }).ToList()
    }).ToList();