实体框架在添加对象后不会加载导航属性

3

我有一个MVC项目和EF6模型。

enter image description here

懒加载已启用。在控制器中,我有以下操作。
    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);
            }
        }
    }

在ListEmployees方法中,为什么foreach语句中stage.Employee == null?如果我第二次调用AddStage,那么ListEmployee中的stage.Employee != null。

它是否已保存在您的数据库中?您在阶段中声明了Employee属性为虚拟的吗? - cverb
数据已保存到数据库。员工属性是虚拟的。 - user2049622
3个回答

9

这是因为您只是设置了外键属性(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};

See MSDN


3

new Stage()

不要对EF对象使用此方法,否则你将无法获得正确的代理对象,以便进行延迟加载导航属性。你需要使用类似于 dbContext.Set<Stage>().Create() 的方法。


1
使用 dbContext.Set<Stage>().Create() 而不是创建新对象是我的解决方案。 - Joanvo

0

我认为在Stage类中拥有EmployeeID,并且Employee对象具有一个ID属性可能会让事情变得混乱。我实际上没有看到你将Employee分配给Stage的地方。我希望看到像这样的东西:

var stage = new Stage() {EmployeeID = employeeId, StageType = 1, Employee = stageManager};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接