无法更改关系,因为一个或多个外键属性在保存时不可为空
The relationship could not be changed because one or more of the foreign-key properties is non-nullable on saving
我使用 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))
);
}
我执行以下操作:
- 添加新组,保存并重新加载
- 将用户添加到群组,保存并重新加载
- 添加第二个用户,保存并重新加载
- 添加第三个用户,尝试保存 -> 抛出异常
在调试时,添加的用户实体的状态始终是分离的,对于新实体,GroupId
和 Id
都设置为 0。前 2 个添加的用户保存成功。但是,在第三个上,抛出异常。
如果,我总是使用相同的方法保存,为什么它并不总是有效?这是 EF
还是 GraphDiff
问题,有没有办法解决这个问题?
这里和其他地方的大多数问题和相关答案都处理子实体被删除的情况。在我的特定情况下情况并非如此。
您是否尝试查看在未被 EF 跟踪时是否正在修改实体状态?
尝试
db.Entry(currentUser).State = EntityState.Modified;
ToList() 函数也可能导致您意外修改用户状态。
请尝试 this.it 虽然尚未测试
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))
);
}
可能与 UserId 不可为空有关。大家知道,UserId是EF用来写User的。如果 User 为空(可以),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 了解这是多对多关系,将创建关联 table (UsersGroups),但您不需要关联实体。
编辑
很少需要使用 EF6 设置 db.Entry(myEntity).State = EntityState.Modified;
。代理效果很好。
我使用 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))
);
}
我执行以下操作:
- 添加新组,保存并重新加载
- 将用户添加到群组,保存并重新加载
- 添加第二个用户,保存并重新加载
- 添加第三个用户,尝试保存 -> 抛出异常
在调试时,添加的用户实体的状态始终是分离的,对于新实体,GroupId
和 Id
都设置为 0。前 2 个添加的用户保存成功。但是,在第三个上,抛出异常。
如果,我总是使用相同的方法保存,为什么它并不总是有效?这是 EF
还是 GraphDiff
问题,有没有办法解决这个问题?
这里和其他地方的大多数问题和相关答案都处理子实体被删除的情况。在我的特定情况下情况并非如此。
您是否尝试查看在未被 EF 跟踪时是否正在修改实体状态?
尝试
db.Entry(currentUser).State = EntityState.Modified;
ToList() 函数也可能导致您意外修改用户状态。
请尝试 this.it 虽然尚未测试
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))
);
}
可能与 UserId 不可为空有关。大家知道,UserId是EF用来写User的。如果 User 为空(可以),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 了解这是多对多关系,将创建关联 table (UsersGroups),但您不需要关联实体。
编辑
很少需要使用 EF6 设置 db.Entry(myEntity).State = EntityState.Modified;
。代理效果很好。