EF Code第一关系错误:违反了多重约束

时间:2016-04-12 14:34:55

标签: c# entity-framework ef-fluent-api

错误

  

违反了多重性约束。角色' Employee_EmployeeToGeoAreas_Source'关系' Domain.Employee_EmployeeToGeoAreas'具有多重性1或0..1。

我在这里处理三种类型的实体:Employee,GeoArea和EmployeeToGeoArea。我有一个编辑框,可以为员工编辑GeoAreas,通过API发回的Employee对象(编辑与否)。

public partial class Employee
{
    public int ID { get; set; }
    public virtual ICollection<EmployeeToGeoArea> EmployeeToGeoAreas { get; set; }
    public Employee()
    {
        EmployeeToGeoAreas = new HashSet<EmployeeToGeoArea>();
    }
}

public class EmployeeMap : EntityTypeConfiguration<Employee>
{
    public EmployeeMap()
    {
        ToTable("Employee");
        this.HasMany(e => e.EmployeeToGeoAreas)
            .WithRequired(e => e.Employee)
            .WillCascadeOnDelete(false);
    }
}

public partial class GeoArea
{
    public int ID { get; set; }
    public virtual ICollection<EmployeeToGeoArea> EmployeeToGeoAreas { get; set; }  
    public GeoArea()
    {
        EmployeeToGeoAreas = new HashSet<EmployeeToGeoArea>();
    }
}

public class GeoAreaMap : EntityTypeConfiguration<GeoArea>
{
    public GeoAreaMap()
    {
        this.ToTable("GeoArea");

        // Primary Key
        this.HasKey(t => t.ID);

        this.HasMany(e => e.EmployeeToGeoAreas)
            .WithRequired(e => e.GeoArea)
            .WillCascadeOnDelete(false);
    }
}

public partial class EmployeeToGeoArea
{
    public int EmployeeID { get; set; }

    public int GeoAreaID { get; set; }

    public int? SchedulePriorityRanking { get; set; }

    public virtual Employee Employee { get; set; }

    public virtual GeoArea GeoArea { get; set; }
}

public class EmployeeToGeoAreaMap : EntityTypeConfiguration<EmployeeToGeoArea>
{
    public EmployeeToGeoAreaMap()
    {
        this.ToTable("EmployeeToGeoAreas");

        // Primary Key
        this.HasKey(t => new { t.EmployeeID, t.GeoAreaID });

        // Properties
        this.Property(t => t.EmployeeID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

        this.Property(t => t.GeoAreaID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

        // Relationships
        this.HasRequired(t => t.Employee)
            .WithMany(t => t.EmployeeToGeoAreas)
            .HasForeignKey(d => d.EmployeeID);

        this.HasRequired(t => t.GeoArea)
            .WithMany(t => t.EmployeeToGeoAreas)
            .HasForeignKey(d => d.GeoAreaID);
    }
}

在这里,我删除了实体上的EmployeeToGeoAreas并添加了新的EmployeeToGeoAreas。可能会添加新的geoAreas,删除旧的geoAreas,或者根本不会发生任何事情。我希望EF能够聪明地处理这个桥牌表。

[HttpPut]
[Route("{employeeId:int:min(1)}")]
public async Task<IHttpActionResult> PostEmployee(EmployeeViewModel viewModel)
{
    var employee = Mapper.Map<EmployeeViewModel, Employee>(viewModel);
    await _employeeRepository.UpdateEmployeeAsync(employee, viewModel.GeoAreas.Select(ga => ga.Id));
    await _employeeRepository.SaveAsync();

    return Ok(viewModel); //TODO: Maybe redirect to employee find?
}

public async Task UpdateEmployeeAsync(Employee employee, IEnumerable<int> geoAreas)
{
    var entity = await Context.Set<Employee>()
        .Include(e => e.EmployeeToGeoAreas)
        .FirstOrDefaultAsync(e => e.ID == employee.ID);

    entity.EmployeeToGeoAreas.Clear();

    foreach (var geoArea in geoAreas)
    {
        var ga = await Context.Set<GeoArea>().FirstOrDefaultAsync(g=> g.ID == geoArea);
        entity.EmployeeToGeoAreas.Add(new EmployeeToGeoArea()
        {
            Employee = employee,
            EmployeeID = employee.ID,
            GeoArea = ga,
            GeoAreaID = ga.ID
        });
    }

    UpdateEntity(entity);
} 

这是应用程序炸弹的地方。

protected virtual void UpdateEntity(T entity)
{
    if (entity is IReadOnlyEntity)
        throw new InvalidOperationException();

    DbEntityEntry entry = Context.Entry(entity); //This is where it throws Multiplicity constraint violated
    if (entry.State == EntityState.Detached)
        Set.Attach(entity);

    entry.State = EntityState.Modified;
}

0 个答案:

没有答案