2

假设我们有一个简单的模式:

Employee
--------
Id
EmployeeName


Project
-------
Id
ProjectName


EmployeeProject
---------------
EmployeeId
ProjectId

在早期版本的 EF 中,我记得连接表被添加到模型中(或者它可能总是被省略,我正在考虑一个有额外列的表)。在 EF 6 中,表格被省略,模型如下所示:

英孚模型

有没有办法在不首先查询数据库以获得适当的实体的情况下向联结表添加行?例如,如果我想创建一个新项目,我可能会从前端获取一个员工 ID 列表;我必须查询数据库以获取员工,然后将它们添加到项目的员工集合中,然后再次访问数据库进行保存。有没有办法只调用一次数据库就可以做到这一点?

更新

这是我要解决的示例(伪代码):

CreateProject (string name, List<int> employeeIds)
{
    var proj = new Project;
    proj.ProjectName = name;
    context.Projects.Add(proj);

    foreach(var id in employeeIds)
    {
        // we have the id, but we need to get the actual Employee entity by hitting the database
        var employee = context.Employees.First(e => e.Id == id); 
        proj.Employees.Add(employee);
    }

    context.SaveChanges();
}

如果模型中存在连接表,我可以简单地执行以下操作:

CreateProject (string name, List<int> employeeIds)
{
    var proj = new Project;
    proj.ProjectName = name;
    context.Projects.Add(proj);

    foreach(var id in employeeIds)
    {
        var empProj = new EmployeeProject();
        empProj.Project = proj;

        // we don't have the Employee entity, but we can set the Id and everything works.
        empProj.EmployeeId = id;  

        context.EmployeeProjects.Add(empProj);
    }

    context.SaveChanges();  // only need to hit database once, after all entities have been added
}
4

2 回答 2

4

不必先检索项目。使用断开连接的对象时,您只需附加现有实体或将状态更改为Unchanged.

实体框架负责跟踪实体连接到上下文时的状态,但在断开连接或 N 层场景中,您可以让 EF 知道您的实体应该处于什么状态。

更多:http: //msdn.microsoft.com/en-us/data/jj592676

您可以只附加员工以减少数据库往返。

foreach(var id in employeeIds)
{
    var employee = new Employe { Id = id }; 
    db.Set<Employee>().Attach(employee); // context.Entry(employee).State = EntityState.Unchanged;
    proj.Employees.Add(employee);
}
于 2014-08-11T18:04:21.683 回答
1

EF 为您处理一切;你可以忽略它。只需将员工添加到 Project.Employees 集合和/或将项目添加到 Employee.Projects 集合,它就会为您处理联结表。删除时相同:只需从集合中删除对象,联结表行将被删除。

澄清后编辑:如果您正在使用 EF 对象,则必须通过 EF 获取现有 EF 对象的实例。使用 EF 时,您不会保留员工 ID 列表;您保留一份员工名单。EF 跟踪它所知道的东西:如果你只是创建一个空白对象并填充东西,EF 会认为它是一个新对象。

于 2014-08-11T16:35:23.253 回答