我对EF并不满意,所以也许这很容易。
我有
public void DeleteLicense(int licenseId)
{
var entityToDelete = context.Licenses.Find(licenseId);
context.Licenses.Remove(entityToDelete);
}
我检查了它是否找到了正确的许可证,并且上下文是ninject(每个请求一个)DbContext,
但是,当我运行上面的函数后,在上下文中调用SaveChanges()时,出现了一个奇怪的错误。我得到:“ CustomerName字段为必填。 ”
现在这很奇怪,因为CustomerName位于帐户(不是许可证)中,但仍已链接。因此,这里有更多内容:
我的帐户实体
[Required]
public String CustomerName { get; set; }
public virtual ICollection<License> Licenses { get; set; }
...
我的许可证实体
public virtual Account Account { get; set; }
...
我的流利设置
modelBuilder.Entity<Account>().HasMany(x => x.Licenses)
.WithRequired(x => x.Account).WillCascadeOnDelete(false);
我不明白,因为即使约束失败,为什么还要缺少CustomerName。自删除许可证以来,我并没有触摸CustomerName,而是设置了CustomerName。
更新
因此,这是代码中的更多详细信息。据我所知,完整的执行路径是
下面的DeleteLicenseAPI进行调用,ID正确,并将其传递给私有函数。私有函数调用问题顶部附近显示的DeleteLicense。在提交()只要求context.SaveChanges();
public ActionResult DeleteLicenseAPI(int licenseId)
{
if (DeleteLicense(licenseId))
{
return Content("ok");
}
return Content("[[[Failed to delete license]]]");
}
private bool DeleteLicense(int licenseId)
{
//todo: sort out busniess rules for delete, is cascaded?
_accountRepository.DeleteLicense(licenseId);
_accountRepository.Commit();
return true;
}
该_accountRepository这个样子的
public class EFAccountRepository : EntityFrameworkRepository<Account>
, IAccountRepository
public EFAccountRepository(EvercateContext context) : base(context)
{
}
这是Ninject中设置所有代码的代码
kernel.Bind<EvercateContext>()
.To<EvercateContext>()
.InRequestScope()
.WithConstructorArgument("connectionStringOrName", "EvercateConnection");
kernel.Bind<IAccountRepository>().To<EFAccountRepository>();
因此,就我所知,即使我使用工作单位(也不应该),在运行SaveChanges之前,此请求中也没有其他要求。有什么方法可以查看DbContext在SaveChanges上将执行的操作,而无需实际运行该方法(因为它会抛出DbEntityValidationException)
我可以想象如果您像这样Account
在License
构造函数中初始化navigation属性,可能会发生这种奇怪的异常:
public License
{
Account = new Account();
}
呼叫时的流程...
var entityToDelete = context.Licenses.Find(licenseId);
context.Licenses.Remove(entityToDelete);
...可能是:
License
实体被加载(没有导航属性Account
)并附加到上下文(状态Unchanged
)Account
导航属性,但未附加(状态Detached
)Remove
,License
实体DetectChanges
由EF内部调用。它检测到License.Account
引用了一个分离的实体,并将其附加到上下文(处于状态Added
)。的状态License
更改为Deleted
。SaveChanges
变更跟踪器时,将找到两个实体:License
in状态Deleted
和Account
in state Added
。CustomerName
的实体的必需属性为(因为仅调用的默认构造函数)。Account
null
Account
我不确定细节是否正确,但是类似的事情可能正在发生。
无论如何,都应Account = new Account();
从License
构造函数中删除,并检查是否在代码库中的实体构造函数中还初始化了其他参考导航属性。(可以初始化空的导航集合。)这是众所周知的奇怪问题的常见原因,这些问题很难发现和理解。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句