EF 6使用现有外键添加对象

时间:2017-11-20 20:48:30

标签: c# entity-framework

我使用的是Entity Framework,我有表Employee和Position。员工参考了职位。

Table("Employee")]
public partial class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Phone { get; set; }
    public int Position_Id { get; set; }
    public decimal Salary { get; set; }

    public virtual Position Position { get; set; }

     [Table("Position")]
public partial class Position
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Position()
    {
        Employee = new HashSet<Employee>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Employee> Employee { get; set; }
}

在位置我已经有物品,我让他们下拉。我想要做的就是使用Position的项目创建Employee的新记录,我从下拉列表中获取该ID。我不想创建新职位。我试过这个:

PositionId是一个属性,ToEmployee()是viewModel

中的方法
public Data.Models.Employee ToEmployee()
    {
        return new Data.Models.Employee
        {
            Name = Name,
            Surname = Surname,
            Phone = Phone,
            Salary = Salary.HasValue ? Salary.Value : 0,
            Position = new Data.Models.Position { Id = PositionId } 
        };
    }

在控制器中添加:

var toModel = viewModel.ToEmployee();
_employeeService.Create(toModel);

但是这创造了新员工和新职位,但我希望只有新的Empoloyee以及员工和职位之间的关系。如何在EF中完成?

当我在ToEmployee()中尝试此操作时:

Position_Id = PositionId

返回错误InvalidColumn。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

显然,职位有零个或多个员工,每个员工只属于一个职位。一个真实的one-to-many relation.

请注意,您选择不遵循entity framework naming conventions。我认为导致问题的一个原因是你没有使用Position的外键的默认命名。您使用Position_Id而不是PositionId。

以下是标准的。由于此标准遵循命名约定,因此不需要流畅的API或任何属性

class Position
{
    public int Id {get; set;}
    // a Position has zero or more Employees:
    public virtual ICollection<Employee> Employees {get; set;}
    ...
}
class Employee
{
    public int Id {get; set;}
    // every Employee belongs to exactly one Position using foreign key:
    public int PositionId {get; set;}
    public virtual Position Position {get; set;}
    ... 
}

如果您确实有充分的理由为外键使用不同的标识符,则必须告诉实体框架哪个标识符包含外键。这是在DbContext.OnModelCreating

中完成的
public override void OnModelCreating(...)
{
    modelBuilder.Entity<Position>()
         // a position has zero or more Employees via property Employees
         .HasMany(position => position.Employees)
         // every Employee has exactly one Position
         .WithRequired(employee => employee.Position)
         // using foreign key Position_id
         .HasForeignKey(employee => employee.Position_Id);
}

现在,只要您拥有有效PositionId的现有职位,并且想要添加具有此职位的员工,您就可以选择填写PositionId或职位:

Position existingPosition = ...;

Employee Employee1 = myDbContext.Employees.Add(new Employee()
{
    Position = existingPosition;
    ...
}
Employee Employee2 = myDbContext.Employees.Add(new Employee()
{
    PositionId = existingPosition.Id;
    ...
}

两者都有效。实体框架非常智能,只能在SQL语句中使用Position.Id。

同样,您可以在一个语句中添加新的职位和员工:

Employee Employee1 = myDbContext.Employees.Add(new Employee()
{
    Position = new Position() {...}
    ...
}

或者添加一个包含多个新员工的新职位:

Position addedPosition = new Position()
{
    Employees = new List<Employee>()
    {
        new Employee() {...},
        new Employee() {...},
        new Employee() {...},
    }
    ...
}

还有其他一些偏差。它们可能不会引起问题,但如果没有理由,为什么会偏离标准?

  • 包含ICollection<Employee>的属性未以复数Employees命名。
  • 让构造函数创建一个HashSet,它不在查询中使用

DbSet代表数据库中的表。你确定这个表有一个HashSet吗?如果您使用Employees对Position进行查询,并在调试器中检查Employee集合的实际类,您将看到它不是HashSet。那么为什么要创建一个?

答案 1 :(得分:0)

在DB中查找Position对象并将其传递给ToEmployee()方法

    public Data.Models.Employee ToEmployee(Data.Models.Position position)
    {
        return new Data.Models.Employee
        {
            Name = Name,
            Surname = Surname,
            Phone = Phone,
            Salary = Salary.HasValue ? Salary.Value : 0,
            Position = position 
        };
    }