保存数据库上下文时出现以下异常:无法更改关系,因为一个或多个外键属性不可为空。
如此处所述,这可能是由于缺少级联删除。但是,这不是我的代码,我不知道哪些表可能包含孤立记录。错误消息没有这样说。
有没有办法检索那些孤儿记录。(至少知道他们在哪个表)
然后我将能够确定我需要调整代码的哪一部分。
保存数据库上下文时出现以下异常:无法更改关系,因为一个或多个外键属性不可为空。
如此处所述,这可能是由于缺少级联删除。但是,这不是我的代码,我不知道哪些表可能包含孤立记录。错误消息没有这样说。
有没有办法检索那些孤儿记录。(至少知道他们在哪个表)
然后我将能够确定我需要调整代码的哪一部分。
在实体框架中,当您具有多对多关系时,您尝试从这样的对象中删除parent.Children.Remove(child)
只会将子对象与中间连接表分离。因此,您必须像这样找到孩子并将其从 DbContext ChildrenToParent 实体中删除DbContext.ChildrenToParent.Remove(child)
。如果您提供一些代码示例和/或数据库图,我想我可以更准确地解释它。
Can you try the following solution? The DeleteOrphans extension method must be called between DetectChanges and SaveChanges methods.
public static class DbContextExtensions
{
private static readonly ConcurrentDictionary< EntityType, ReadOnlyDictionary< string, NavigationProperty>> s_navPropMappings = new ConcurrentDictionary< EntityType, ReadOnlyDictionary< string, NavigationProperty>>();
public static void DeleteOrphans( this DbContext source )
{
var context = ((IObjectContextAdapter)source).ObjectContext;
foreach (var entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
{
var entityType = entry.EntitySet.ElementType as EntityType;
if (entityType == null)
continue;
var navPropMap = s_navPropMappings.GetOrAdd(entityType, CreateNavigationPropertyMap);
var props = entry.GetModifiedProperties().ToArray();
foreach (var prop in props)
{
NavigationProperty navProp;
if (!navPropMap.TryGetValue(prop, out navProp))
continue;
var related = entry.RelationshipManager.GetRelatedEnd(navProp.RelationshipType.FullName, navProp.ToEndMember.Name);
var enumerator = related.GetEnumerator();
if (enumerator.MoveNext() && enumerator.Current != null)
continue;
entry.Delete();
break;
}
}
}
private static ReadOnlyDictionary<string, NavigationProperty> CreateNavigationPropertyMap( EntityType type )
{
var result = type.NavigationProperties
.Where(v => v.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
.Where(v => v.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One || (v.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne && v.FromEndMember.GetEntityType() == v.ToEndMember.GetEntityType()))
.Select(v => new { NavigationProperty = v, DependentProperties = v.GetDependentProperties().Take(2).ToArray() })
.Where(v => v.DependentProperties.Length == 1)
.ToDictionary(v => v.DependentProperties[0].Name, v => v.NavigationProperty);
return new ReadOnlyDictionary<string, NavigationProperty>(result);
}
}