C# 向DbContext添加新对象时实体框架中出现空引用异常
将新对象添加到DbContext时,我从Entity Framework内部抛出了一个C# 向DbContext添加新对象时实体框架中出现空引用异常,c#,entity-framework,C#,Entity Framework,将新对象添加到DbContext时,我从Entity Framework内部抛出了一个nullreferenceexception 堆栈跟踪: at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.GetOtherEndOfRelationship(IEntityWrapper wrappedEntity) at System.Data.Entity.Core.Objects.EntityEntry.AddRelationshi
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不为null。仔细检查newFoo可以发现newFoo内部有大量null属性,但它们都允许为null
根据stacktrace,我假设这与集合属性有关。因此,我更仔细地检查了集合属性,发现集合中没有一个为null,集合对象的FK属性中也没有一个为null。由于实体框架抛出了错误,并且我无法进入实体框架代码,我很难找到准确的错误。经过一些努力,我将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
{
公共int Id{get;set;}
公共列表FooBars{get;set;}
}
公共类酒吧
{
公共int Id{get;set;}
公共列表FooBars{get;set;}
}
公共级FooBar
{
[键,列(顺序=1)]
公共int FooId{get;set;}
公共Foo Foo{get;set;}
[键,列(顺序=2)]
公共int BarId{get;set;}
公共条{get;set;}
public RelationshipEnum关系{get;set;}
}
所有这些都是为了在Foo和Bar之间创建一个关系,该关系还指定了关系的类型
我从外部来源读取数据并创建或更新这些关系。问题出在我的更新代码中:
我草率地决定了我要更新的是哪种FooBar关系。如果我碰巧尝试更新错误的密钥,我将尝试更改一个不允许的复合密钥
我通过向我的FooBar类添加一个Id属性并按该属性排序来修复此问题,以确保始终按照添加顺序从数据库中检索该属性。我还必须清除所有旧数据(我想修复它可能会奏效,但因为我可以从我的外国来源重新提取数据,所以只需删除数据并重新提取就更容易了)
关于实体框架如何工作,我收集了一些额外的数据:
当使用DbSet.Add(T entry)
方法时,它会检查所有加载的条目中的更改,而不仅仅是您添加的条目,这就是为什么我在没有可确定模式的每个添加上都会出错的原因。对于我试图添加的每个条目,它在同一条目中发现相同的错误
TL;DR
我的代码试图以一种奇怪的方式更改对象上的复合键,这会导致实体框架在验证所有加载项上的关系时阻塞(每次调用时都会添加一个新项)。您的newFoos对象是否包含任何数据?您在哪一行发现错误?我不是业余程序员。我知道如何调试空引用异常。通过查看堆栈跟踪可以看到,此空引用异常发生在实体框架内部。我的代码都没有抛出错误。我需要比我更擅长实体框架的人为我指明正确的方向。
我不是业余程序员。
这很公平。道歉。只是很沮丧。我想我不认为这是我的NRE。因为错误不在我的代码中。或者,更确切地说,我的代码没有抛出异常。我承认我的代码中可能有错误,可能是在不应该设置的地方将某些内容设置为null。我已经在谷歌上搜索和研究了一个星期了,我已经阅读了所有关于堆栈溢出的帖子(和一些MSDN),这些帖子甚至有点不相关。我验证了我的POCO中的PK/FK都已对齐。我只是想。。。你能给我一个答案吗?Foo
的模型定义、Foo
的EF映射,以及将产生相同错误的Foo
的基本初始化(不复制状态)。