我有MVC项目和EF6模型。
启用了LazyLoading。在控制器中,我有以下行动
public ActionResult AddStage(int projectId, int employeeId)
{
using(var context = new TestProjectEntities())
{
var project = context.Projects.Find(projectId);
if (project != null)
{
var stage = new Stage() {EmployeeID = employeeId, StageType = 1};
project.Stages.Add(stage);
context.Stages.Add(stage);
context.SaveChanges();
}
ListEmployees(project);
}
return Redirect("Index");
}
private void ListEmployees(Project project)
{
var names = new List<string>();
foreach(var stage in project.Stages)
{
if (stage.Employee != null)
{
names.Add(stage.Employee.Name);
}
}
}
但是在foreach语句中的ListEmployees方法stage.Employee == null中。 为什么呢?
如果我第二次调用AddStage,那么ListEmployee中的stage.Employee!= null
答案 0 :(得分:8)
那是因为您只是设置了外键属性(Stage.EmployeeID
)而没有设置导航属性(Stage.Employee
)。
通常,在调用SaveChanges()
之后,EF也会更新导航属性。但是,由于Stage
对象是由您手动创建的,因此未对其进行跟踪(使用DynamicProxy),并且您必须明确修复关系:
context.Entry(stage).Reference(c => c.Employee).Load();
另一种方法是获取Employee
并使用它而不是设置外键属性:
var employee = context.Employees.Find(employeeId);
var stage = new Stage() { Employee = employee, StageType = 1};
请参阅MSDN
答案 1 :(得分:2)
new Stage()
不要对EF对象执行此操作。您将无法获得可以延迟加载导航属性的正确代理对象。您需要使用类似dbContext.Set<Stage>().Create()
答案 2 :(得分:0)
我认为在EmployeeID
类中使用Stage
并使Employee
对象具有ID
属性可能会令人困惑。我实际上看不到您为Employee
分配Stage
的位置。我希望看到这样的事情:
var stage = new Stage() {EmployeeID = employeeId, StageType = 1, Employee = stageManager};