无法更改关系,因为一个或多个外键属性在保存时不可为空

时间:2016-04-14 12:01:32

标签: c# entity-framework entity-framework-6 graphdiff

我使用GraphDiff更新分离的对象图,我在保存父级及其子级时遇到上述异常。

模型和映射是:

public class Group
{
    public int Id { get; set; }
    public virtual ICollection<GroupUser> Users{ get; set; }
}

public class GroupUser
{
    public int Id { get; set; }
    public int GroupId { get; set; }
    public int UserId { get; set; }
    public virtual User User { get; set; }
}

public class GroupMap : EntityTypeConfiguration<Group>
{
    public GroupMap()
    {
        this.ToTable("groups");
        this.HasKey(t => t.Id).Property(t => t.Id).HasColumnName("id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        this.HasMany(t => t.Users)
            .WithOptional()
            .HasForeignKey(d => d.GroupId)
            .WillCascadeOnDelete();
    }
}

public class GroupUserMap : EntityTypeConfiguration<GroupUser>
{
    public GroupUserMap ()
    {
        this.ToTable("groups_users");
        this.HasKey(t => t.Id).Property(t => t.Id).HasColumnName("id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(t => t.GroupId).HasColumnName("group_id").IsRequired();
        this.Property(t => t.UserId).HasColumnName("user_id").IsRequired();

        this.HasRequired(t => t.User)
            .WithMany()
            .HasForeignKey(d => d.UserId)
            .WillCascadeOnDelete(false);
    }
}

对于插入和更新,我在我的存储库中有以下方法:

public override Group Update(Group entity)
{
    if (entity.Users != null)
    {
        entity.Users.ToList()
                    .ForEach(x =>
                    {
                        x.GroupId = x.Id == 0 ? 0 : entity.Id;
                        x.UserId = x.User.Id;
                    });
    }

    return dbContext.UpdateGraph<Group>
        (entity,
            map => map.OwnedCollection(x => x.Users, with => with.AssociatedEntity(c => c.Users))
        );
}

我执行以下操作:

  1. 添加新组,保存并重新加载
  2. 将用户添加到群组,保存并重新加载
  3. 添加第二个用户,保存并重新加载
  4. 添加第三个用户,尝试保存 - &gt;异常被抛出
  5. 在调试时,添加的用户实体的状态始终是分离的,新实体的GroupIdId都设置为0。添加的前2个用户已成功保存。但是,在第三个问题上,抛出异常。

    如果,我总是使用相同的方法进行保存,为什么它总是不起作用?是EF还是GraphDiff问题,有没有办法解决这个问题?

    SO和其他地方的大多数问题和相关答案都涉及删除子实体的情况。在我的特定情况下情况并非如此。

3 个答案:

答案 0 :(得分:1)

您是否尝试过在未被EF跟踪时是否正在修改实体状态?

尝试

db.Entry(currentUser).State = EntityState.Modified;

ToList()函数也可能导致您意外修改用户状态。

答案 1 :(得分:0)

请尝试这个。虽然未经测试

public override Group Update(Group entity)
{
    if (entity.Users != null)
    {
        foreach(var user in entity.Users){
          user.GroupId = x.Id == 0 ? 0 : entity.Id;
          user.UserId = x.User.Id;
         dbContext.Entry(child).State = EntityState.Modified;
        }

    }

    return dbContext.UpdateGraph<Group>
        (entity,
            map => map.OwnedCollection(x => x.Users, with => with.AssociatedEntity(c => c.Users))
        );
}

答案 2 :(得分:0)

可能与UserId无关可空。如您所知,EF使用UserId来编写用户。如果User为null(可以),则EF无法写入实体。 此外,它可能与EF用于映射Group.Users集合的User.GroupId相关。

另外,我无法理解你的模特。 用户只有一个组。 一个组可以拥有多个用户。

如果这是真的,为什么不简化模型删除关联实体? EF不需要它......

public class Group
{
    public int Id { get; set; }
    public virtual ICollection<User> Users{ get; set; }
}

public class User
{
    public int Id { get; set; }
    public virtual Group Group { get; set; }
}

在这种情况下,您只需要UserMap。

public class UserMap : EntityTypeConfiguration<User>
{
    public UserMap()
    {
        // You don't need to set primary key. EF take Id and create an identity column
        //HasKey(t => t.Id); 

        // Table & Column Mappings
        ToTable("users");
        // No column mappings in this case.

        // Relationships
        HasRequired(t => t.Group)
            .WithMany(t => t.Users)
            .Map(d => d.MapKey("user_group"));

    }
}

如果用户可以拥有多个组,则可以通过这种方式修改用户模型

public class User
{
    public int Id { get; set; }
    public virtual ICollection<Group> Groups { get; set; }
}

EF了解这是一个多对多的关系,会创建关联表(UsersGroups)但你不需要关联实体。

编辑

您很少需要使用EF6设置db.Entry(myEntity).State = EntityState.Modified;。代理工作得非常好。