1

我刚刚完成了一些代码的重构,现在在保存DbContext以下一些不应受我刚刚所做的更改影响的计算代码时出现此错误。

错误是:

{“无法将 'System.Collections.Generic.List`1[_3T.NewDomain.Quote.Pricing.PriceLineItem]' 类型的对象转换为 '_3T.NewDomain.Quote.Pricing.PriceLineItem' 类型。”}

调用时触发:DbContext.SaveChanges()

我将着手进行我预期的相当漫长的调试过程。但是,我对代码如何编译好感到完全困惑。然而,DbContext它试图将列表分配给单个实例变量。

有没有人遇到过会导致这样的事情?我忽略了什么?

4

1 回答 1

2

我找到了答案。我把它贴在这里以防它帮助别人。

鉴于错误与 EF 相关,并且代码已编译,我开始假设它很可能是配置错误。

提供一些附加信息:PriceLineItem位于错误焦点的类可以嵌套在其自身中,从而提供树结构。还有一些类继承自PriceLineItem,例如IssuePriceLineItem.

在我开始使用这种新的树结构的早期,我DbContext使用 fluent API 在我的类中手动定义了以下配置:

 modelBuilder.Entity<IssuePriceLineItem>()
   .HasOptional(p => p.PriceLineItems)
   .WithMany()
   .HasForeignKey(c => c.ParentLineItemId);

修补阶段的遗物就是错误所在。你可以看到它暗示了一个多对多的关系。这可以通过更改此配置的第 2 行或第 2 行和第 3 行来解决。

更正1:

 modelBuilder.Entity<IssuePriceLineItem>()
   .HasOptional(p => p.ParentLineItem)
   .WithMany() /* implies ICollection<PriceLineItem> PriceLineItems */
   .HasForeignKey(c => c.ParentLineItemId);

更正2:

 modelBuilder.Entity<IssuePriceLineItem>()
   .HasMany(p => p.PriceLineItems)
   .WithOptional() /* implies ParentLineItem navigation property */
   .HasForeignKey(c => c.ParentLineItemId);

无论哪种方式,在这种特定情况下,我都应该将其定义为使用PriceLineItem而不是自引用IssuePriceLineItem。如果它从一开始就是自引用的,那么错误的配置就会更早地暴露出来。而不是一直处于休眠状态,直到我最近的重构开始发挥作用。

在我看来,最安全的配置定义更明确,如下所示:

  modelBuilder.Entity<PriceLineItem>()
    .HasOptional(p => p.ParentLineItem)
    .WithMany(p => p.PriceLineItems)
    .HasForeignKey(c => c.ParentLineItemId);

但是,最好的解决方法 (IMO) 是完全删除此条目。由于使用了属性名称,因此约定优于配置足以处理此关系定义

于 2013-11-11T10:51:58.097 回答