MemberDomainMap中的实体框架CodeFirst KeyNotFoundException

时间:2012-11-29 04:31:49

标签: entity-framework-4.3

尝试在我的EF datacontext实现中运行错误,这会产生相当神秘的错误。

Test Name:  Nodes_can_be_saved
Test FullName:  MyProj.Test.Integration.AFDataContextTest.Nodes_can_be_saved
Test Source:    c:\Users\pvencill. \Documents\Visual Studio 2012\Projects\MyProj\MyProj.Test\Integration\AFDataContextTest.cs : line 49
Test Outcome:   Failed
Test Duration:  0:00:01.4192808

Result Message: 
Test method MyProj.Test.Integration.AFDataContextTest.Nodes_can_be_saved threw exception: 
System.Data.Entity.Infrastructure.DbUpdateException: Error retrieving values from ObjectStateEntry. See inner exception for details. ---> System.Data.UpdateException: Error retrieving values from ObjectStateEntry. See inner exception for details. ---> System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
Result StackTrace:  
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at System.Data.Mapping.ViewGeneration.Structures.MemberDomainMap.GetDomainInternal(MemberPath path)
   at System.Data.Mapping.ViewGeneration.QueryRewriting.FragmentQueryKB.CreateIsOfTypeCondition(MemberPath currentPath, IEnumerable`1 derivedTypes, MemberDomainMap domainMap)
   at System.Data.Mapping.ViewGeneration.QueryRewriting.FragmentQueryKB.CreateVariableConstraintsRecursion(EdmType edmType, MemberPath currentPath, MemberDomainMap domainMap, EdmItemCollection edmItemCollection)
   at System.Data.Mapping.ViewGeneration.QueryRewriting.FragmentQueryKB.CreateVariableConstraintsRecursion(EdmType edmType, MemberPath currentPath, MemberDomainMap domainMap, EdmItemCollection edmItemCollection)
   at System.Data.Mapping.ViewGeneration.ViewgenContext..ctor(ViewTarget viewTarget, EntitySetBase extent, IEnumerable`1 extentCells, CqlIdentifiers identifiers, ConfigViewGenerator config, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap, StorageEntityContainerMapping entityContainerMapping)
   at System.Data.Mapping.ViewGeneration.ViewGenerator.CreateViewgenContext(EntitySetBase extent, ViewTarget viewTarget, CqlIdentifiers identifiers)
   at System.Data.Mapping.ViewGeneration.ViewGenerator.GenerateDirectionalViewsForExtent(ViewTarget viewTarget, EntitySetBase extent, CqlIdentifiers identifiers, KeyToListMap`2 views)
   at System.Data.Mapping.ViewGeneration.ViewGenerator.GenerateDirectionalViews(ViewTarget viewTarget, CqlIdentifiers identifiers, KeyToListMap`2 views)
   at System.Data.Mapping.ViewGeneration.ViewGenerator.GenerateAllBidirectionalViews(KeyToListMap`2 views, CqlIdentifiers identifiers)
   at System.Data.Mapping.ViewGeneration.ViewgenGatekeeper.GenerateViewsFromCells(List`1 cells, ConfigViewGenerator config, CqlIdentifiers identifiers, StorageEntityContainerMapping containerMapping)
   at System.Data.Mapping.ViewGeneration.ViewgenGatekeeper.GenerateViewsFromMapping(StorageEntityContainerMapping containerMapping, ConfigViewGenerator config)
   at System.Data.Mapping.StorageMappingItemCollection.ViewDictionary.SerializedGenerateViews(StorageEntityContainerMapping entityContainerMap, Dictionary`2 resultDictionary)
   at System.Data.Mapping.StorageMappingItemCollection.ViewDictionary.SerializedGetGeneratedViews(EntityContainer container)
   at System.Data.Common.Utils.Memoizer`2.<>c__DisplayClass2.<Evaluate>b__0()
   at System.Data.Common.Utils.Memoizer`2.Result.GetValue()
   at System.Data.Common.Utils.Memoizer`2.Evaluate(TArg arg)
   at System.Data.Mapping.StorageMappingItemCollection.ViewDictionary.GetGeneratedView(EntitySetBase extent, MetadataWorkspace workspace, StorageMappingItemCollection storageMappingItemCollection)
   at System.Data.Mapping.Update.Internal.ViewLoader.InitializeEntitySet(EntitySetBase entitySetBase, MetadataWorkspace workspace)
   at System.Data.Mapping.Update.Internal.ViewLoader.SyncInitializeEntitySet[TArg,TResult](EntitySetBase entitySetBase, MetadataWorkspace workspace, Func`2 evaluate, TArg arg)
   at System.Data.Mapping.Update.Internal.ViewLoader.SyncContains[T_Element](EntitySetBase entitySetBase, MetadataWorkspace workspace, Set`1 set, T_Element element)
   at System.Data.Mapping.Update.Internal.ExtractorMetadata..ctor(EntitySetBase entitySetBase, StructuralType type, UpdateTranslator translator)
   at System.Data.Mapping.Update.Internal.UpdateTranslator.GetExtractorMetadata(EntitySetBase entitySetBase, StructuralType type)
   at System.Data.Mapping.Update.Internal.ExtractorMetadata.ExtractResultFromRecord(IEntityStateEntry stateEntry, Boolean isModified, IExtendedDataRecord record, Boolean useCurrentValues, UpdateTranslator translator, ModifiedPropertiesBehavior modifiedPropertiesBehavior)
   at System.Data.Mapping.Update.Internal.RecordConverter.ConvertStateEntryToPropagatorResult(IEntityStateEntry stateEntry, Boolean useCurrentValues, ModifiedPropertiesBehavior modifiedPropertiesBehavior)
 --- End of inner exception stack trace ---
    at System.Data.Mapping.Update.Internal.RecordConverter.ConvertStateEntryToPropagatorResult(IEntityStateEntry stateEntry, Boolean useCurrentValues, ModifiedPropertiesBehavior modifiedPropertiesBehavior)
   at System.Data.Mapping.Update.Internal.ExtractedStateEntry..ctor(UpdateTranslator translator, IEntityStateEntry stateEntry)
   at System.Data.Mapping.Update.Internal.UpdateTranslator.LoadStateEntry(IEntityStateEntry stateEntry)
   at System.Data.Mapping.Update.Internal.UpdateTranslator.PullModifiedEntriesFromStateManager()
   at System.Data.Mapping.Update.Internal.UpdateTranslator.ProduceCommands()
   at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
   at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)
   at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
   at System.Data.Entity.Internal.InternalContext.SaveChanges()
 --- End of inner exception stack trace ---
    at System.Data.Entity.Internal.InternalContext.SaveChanges()
   at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
   at System.Data.Entity.DbContext.SaveChanges()
   at MyProj.Data.MyProjDataContext.SaveChanges() in c:\Users\pvencill. \Documents\Visual Studio 2012\Projects\MyProj\MyProj.Data\MyProjDataContext.cs:line 44
   at MyProj.Test.Integration.AFDataContextTest.Nodes_can_be_saved() in c:\Users\pvencill. \Documents\Visual Studio 2012\Projects\MyProj\MyProj.Test\Integration\AFDataContextTest.cs:line 55

研究这个错误导致谷歌上没有什么点击,但是我发现这些错误表明它与我的模型关系有关,尽管在查看迁移所产生的数据库时,所有这些似乎都在我看来。我的相关模型如下:

我的数据上下文DBSets和modelCreating定义:

public DbSet<Blip> Blips { get; set; }
        public DbSet<SensorAdapter> Sensors { get; set; }
        public DbSet<NodeReport> NodeReports { get; set; }
        public DbSet<Node> Nodes { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blip>().Property(b => b.TimeStamp).HasColumnType("datetime2");
            modelBuilder.Entity<Node>().HasMany<NodeReport>(n => n.NodeReports).WithRequired(nr=>nr.Node);
            modelBuilder.Entity<Blip>().HasMany<NodeReport>(b => b.NodeReports);

            base.OnModelCreating(modelBuilder);
        }

Blips和SensorAdapter对象在将NodeReports添加到它们之前工作正常,所以我怀疑它在那里是项目所在。

我有一个基本的Entity对象,我的所有东西都继承自对象,它只定义了类型为T的Id属性;这工作正常。

NodeReport继承自Report,其定义如下:

public abstract class Report : Entity<long>
    {
        public Report()
        {
            Status = Status.Unknown;
        }

        public DateTime TimeStamp { get; set; }
        public Status Status { get; set; }
        public String Raw { get; set; }
    }

因此定义了NodeReport:

public class NodeReport : Report
    {
        public virtual Node Node { get; set; }
        //public virtual Blip Blip { get; set; }
    }

我在有和没有Blip的情况下尝试了它,当我尝试缩小问题时注释掉了

Node也是一个非常稀疏的类:

public class Node : Entity<long>
    {
        public Node ()
        {
                       NodeReports = new List<NodeReport>();
        }

        public String HostName { get;set; }
        public String Description { get; set; }
            public virtual IList<NodeReport> NodeReports { get; set; }
    }

任何建议都会非常感激,我一直在努力想象它。

3 个答案:

答案 0 :(得分:3)

好吧,经过大量搜索我的代码并从头开始重建后,我发现问题实际上是我有一个派生类的Node,它有一个Uri作为属性,显然由于没有默认值而导致映射失败构造函数(可能还有其他原因)。我现在通过简单地将属性更改为我在内部验证为Uri的String来解决它,尽管我更喜欢更优雅的解决方案。我尝试将Uri甚至是Uri的自定义子类(w /默认构造函数)映射到复杂类型,但这没有帮助。

不过,上面的问题已经回答了。

答案 1 :(得分:1)

通过@Paul的回答,我终于可以找出问题所在。

我正在使用带有继承 TPT EF (每种类型的表格)。

源代码

为了更容易,我将使用this教程中描述的相同类。

public abstract class BillingDetail
{
    public int BillingDetailId { get; set; }
    public string Owner { get; set; }
    public string Number { get; set; }
}

[Table("BankAccounts")]
public class BankAccount : BillingDetail
{
    public string BankName { get; set; }
    public string Swift { get; set; }
    public Agency Agency { get; set; } /* I added it */
}

public class InheritanceMappingContext : DbContext
{
    public DbSet<BillingDetail> BillingDetails { get; set; }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<BankAccount>().ToTable("BankAccounts");
    modelBuilder.Entity<CreditCard>().ToTable("CreditCards");
}

问题

请注意,我在Agency中添加了一个名为BankAccount的新属性。鉴于它是复杂类型,如果你没有映射它,你会在运行时遇到这个恼人的错误!

解决方案

我所做的只是忽略此属性Agency,但您也可以将其映射到EF知道该怎么做。两者都将阻止错误。

最奇怪的是,即使没有映射派生实体(BankAccount),也会出现问题。似乎EF不知何故知道你创建了派生。所以,如果你试图在没有映射某些推导的情况下运行EF,你也可能会得到这个错误。

答案 2 :(得分:0)

我遇到了同样的问题,不幸的是,除了与该问题相关的其他问题的答案之外,StackOverflow中的所有解决方案都没有对我有用。

但是我找到了自己的修复程序,如果与我的问题相同,也可以自己检查。发生的事情是,如果某个类继承自我在DbSet上使用的表:

public DbSet<Employee> Employees { get; set; }

在这种情况下,如果某些其他类从我的POCO Employee继承,则会触发此特定错误。我从此类中删除了所有继承,从而解决了该问题。

请注意,引发此相同问题的继承问题:

The given key was not present in the dictionary.

仅当继承位于同一项目上时才会发生。我试图在其他项目上继承POCO,这很好。