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();
我有一个包含 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();