C# 向DbContext添加新对象时实体框架中出现空引用异常

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

将新对象添加到DbContext时,我从Entity Framework内部抛出了一个
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
的基本初始化(不复制状态)。