我在使用Jerther 的解决方案时遇到了问题,在删除包含 Key Entry 的关系的情况下,抛出了这个异常:
A relationship from the 'TableAValue_TableA' AssociationSet is in the 'Deleted' state. Given multiplicity constraints, a corresponding 'TableAValue_TableA_Source' must also in the 'Deleted' state.
问题似乎是RejectNavigationChanges()
无法将已删除的关系恢复到以前的状态,因为它包含一个 Key Entry,但关联的对象已经由RejectScalarChanges()
.
RejectScalarChanges()
解决方案是将恢复已删除实体的方式更改为使用entry.Reload()
.
我的工作解决方案:
public void RejectChanges()
{
RejectScalarChanges();
RejectNavigationChanges();
}
private void RejectScalarChanges()
{
var changedEntries = _dbContext.ChangeTracker.Entries()
.Where(e => e.State != EntityState.Unchanged);
foreach (var entry in changedEntries)
{
switch (entry.State)
{
case EntityState.Added:
entry.State = EntityState.Detached;
break;
case EntityState.Modified:
entry.State = EntityState.Unchanged;
break;
// Where a Key Entry has been deleted, reloading from the source is required to ensure that the entity's relationships are restored (undeleted).
case EntityState.Deleted:
entry.Reload();
break;
}
}
}
private void RejectNavigationChanges()
{
var objectContext = _dbContext.GetObjectContext();
var addedRelationships = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added)
.Where(e => e.IsRelationship);
var deletedRelationships = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted)
.Where(e => e.IsRelationship && !RelationshipContainsKeyEntry(e));
foreach (var relationship in addedRelationships)
relationship.Delete();
foreach (var relationship in deletedRelationships)
relationship.ChangeState(EntityState.Unchanged);
bool RelationshipContainsKeyEntry(ObjectStateEntry stateEntry)
{
var keys = new[] { stateEntry.OriginalValues[0], stateEntry.OriginalValues[1] };
return keys.Any(key => objectContext.ObjectStateManager.GetObjectStateEntry(key).Entity == null);
}
}