将新对象添加到DbContext时,我从实体框架内部抛出了nullreferenceexception
。
堆栈跟踪:
at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.GetOtherEndOfRelationship(IEntityWrapper wrappedEntity)
at System.Data.Entity.Core.Objects.EntityEntry.AddRelationshipDetectedByForeignKey(Dictionary`2 relationships, Dictionary`2 principalRelationships, EntityKey relatedKey, EntityEntry relatedEntry, RelatedEnd relatedEndFrom)
at System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInForeignKeys()
at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChangesInForeignKeys(IList`1 entries)
at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges()
at System.Data.Entity.Core.Objects.ObjectContext.DetectChanges()
at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)
at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
at System.Data.Entity.DbSet`1.Add(TEntity entity)
导致它的实际代码行:
var convertedFoos = ReadFoosFromForeignSource(); //returns a list of anonymous objects with two fields: Foo Original, Foo Converted
UpdatedFooData(convertedFoos.Where(x => x.Original != null));
var newFoos = convertedFoos.Where(x => x.Original == null).Select(x => x.Converted).ToList();
foreach (Foo newFoo in newFoos)
{
db.Foos.Add(newFoo); //error happens here
}
我正在从外部来源读取Foo XML,并将其转换为本地Foo格式,然后执行以下操作:更新现有对象或将新对象添加到数据库中。
引发错误时(如上面的注释所示),db,db.Foos和newFoo不为空。检查过的newFoo可以更紧密地揭示newFoo内部的大量null属性,但都可以将它们设为null。
基于堆栈跟踪,我正在做假设,它与集合属性有关。因此,我更加仔细地检查了集合属性,发现所有集合都不为空,并且集合对象的FK属性都不为空。
答案 0 :(得分:1)
由于Entity Framework抛出错误,并且由于无法进入Entity Framework代码,因此我难以找到确切的错误。经过一番努力,我将Entity Framework源代码拉到了我的项目中,进行了编译,并像其他任何人一样调试了错误。我发现了问题。
我有:
public class Foo
{
public int Id {get; set;}
public List<FooBar> FooBars {get;set;}
}
public class Bar
{
public int Id {get; set;}
public List<FooBar> FooBars {get; set;}
}
public class FooBar
{
[Key, Column(Order=1)]
public int FooId {get; set;}
public Foo Foo {get; set;}
[Key, Column(Order=2)]
public int BarId {get; set;}
public Bar Bar {get; set;}
public RelationshipEnum Relationship {get; set;}
}
所有这些都是在Foo和Bar之间创建关系,并指定关系的类型。
我正在从外部来源读取数据并创建或更新这些关系。问题出在我的更新代码中:
我在确定要更新的FooBar关系时草率。如果我碰巧尝试更新错误的密钥,那是在尝试更改不允许的组合键之一。
我通过将Id属性添加到FooBar类并对其进行排序来解决此问题,以确保始终按添加顺序从数据库中检索该属性。我还必须清除所有旧数据(我想修复它可能会起作用,但是由于我可以从国外来源重新拉出它,因此删除数据并重新拉出会更容易。)
我收集了一些有关实体框架如何工作的额外数据:
使用DbSet<T>.Add(T entry)
方法时,它会检查所有已加载的条目中的变化,而不仅是您添加的变化,这就是为什么我每次添加都会出错而无法确定的原因图案。对于我尝试添加的每个条目,它都在同一个条目中找到相同的错误。
TL; DR
我的代码试图以一种奇怪的方式更改对象上的组合键,这导致实体框架在验证所有已加载的条目上的关系时(在每次添加新条目的调用中都这样做)导致阻塞。