在 EF6 中,可能导致错误的原因 无法更改关系,因为一个或多个外键属性不可为空
本文关键字:一个 属性 因为 错误 EF6 关系 | 更新日期: 2023-09-27 18:35:44
嗨,我收到此错误消息,仅在一种特定情况下触发。
操作失败:无法更改关系,因为 一个或多个外键属性不可为空。当一个 对关系进行更改,相关的外键属性为 设置为空值。 如果外键不支持空值, 必须定义新关系,外键属性必须 分配了另一个非 null 值,或者不相关的对象必须是 删除。
System.InvalidOperationException 未由用户代码
处理 HResult=-2146233079 消息=操作失败:关系 无法更改,因为一个或多个外键属性 不可为空。当对关系进行更改时,相关的 外键属性设置为 null 值。如果外键确实如此 不支持空值,必须定义一个新关系, 必须为外键属性分配另一个非空值,或者 必须删除不相关的对象。 源=实体框架
堆栈跟踪: at System.Data.Entity.Core.Objects.ObjectContext.PrepareToSaveChanges(SaveOptions 选项) at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions 选项,布尔值执行在现有事务中) at System.Data.Entity.Core.Objects.ObjectContext.SaveChanges(SaveOptions 选项) at System.Data.Entity.Internal.InternalContext.SaveChanges() at System.Data.Entity.Internal.LazyInternalContext.SaveChanges() at System.Data.Entity.DbContext.SaveChanges().....
我有一个信用系统,我的用户可以在其中购买信用额度来执行检查。每次执行检查时,用户拥有的配额数都会递减。
用户表有一个 FK 信用 ID。信用 ID 是信用表的 PK。这可以被认为是 1 对 1 的关系,但我只在用户模型中定义了关系。我将信用分隔到一个单独的表中,以便我可以跟踪用户的信用更改时间以及更改者。
当用户购买积分或执行新检查时,一切正常。但是,如果用户尝试执行重新检查。它会导致错误。我不明白这是怎么发生的?我有一种感觉,上下文中存在冲突,但我不知道在哪里。
public abstract class Repository
{
private readonly DbContext _dataContext;
protected Repository(DbContext dataContext)
{
_dataContext = dataContext;
}
public int SaveChanges()
{
return _dataContext.SaveChanges();
}
}
这在方法中称为
private int SubtractFromCredit(int amount, User user)
{
var now = DateTime.UtcNow;
var credits = user.Credits;
credits.Amount -= amount;
credits.ModifiedDate = now;
credits.ModifiedBy = user.Id;
_creditsRepository.SaveChanges();
return credits.Amount;
}
我不确定为什么这会失败,因为 Credits 表只是用户表中的 FK。当我执行重新检查失败时,添加积分很好,减去学分也可以。
归根结底,我只是想做一个简单的更新行。我不明白这如何导致与 FK 的冲突
在解决此问题时寻找什么的任何帮助都会很棒
你能把这些实体定义添加到你的问题中吗?
如果您使用用户导航到他们的信用,那么我怀疑您需要有两个外键关系。对于用户及其信用,一对多。和其他为信用=>修改者。
事实证明,错误是在代码的误导性部分中抛出的。错误被抛入
private int SubtractFromCredit(int amount, User user)
{
var now = DateTime.UtcNow;
var credits = user.Credits;
credits.Amount -= amount;
credits.ModifiedDate = now;
credits.ModifiedBy = user.Id;
// inside SaveChanges here
_creditsRepository.SaveChanges();
return credits.Amount;
}
但这是由上面调用 SubstractFromCredit 的那行引起的。
tenantCheck.PreviousAddresses = _addressService.AddPreviousAddresses(addresses, tenantCheck, user.Id);
我无法解释我为什么这样做或我当时的想法。但问题是 PreviousAddresses是一个虚拟的 ICollection,它是由 EF 为我填充的。通过手动将其分配给仅 PreviousAddresses(上一个地址)的新记录,EF 不知道如何处理上一个地址的现有记录。
写完这个之后,我会推测错误是在 SubtractFromCredit 中抛出的,因为在分配 PreviousAddresses之后,这是调用数据上下文以保存对数据库的更改的下一个位置