我有一个DbSet,它包含类"周";。类中的属性之一是包含类"的列表;天";。
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; }
}
目前,我正在从控制器中测试数据库。首先,我加载mockdata,将其保存到数据库中,然后再次从数据库中加载数据,以便在页面上显示。
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);
}
保存和返回表格的方法,供参考:
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()
时,您将只获得Weeks,而没有相关的天数。
当您在获取对象图时期望相关数据时,请确保:
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();