使用EF 5向Oracle 11gR2数据库添加订单时,为什么会出现“InvalidOperationException”?

时间:2014-01-13 14:50:53

标签: c# .net oracle entity-framework

为什么在使用EF 5向Oracle 11gR2数据库添加订单时会收到InvalidOperationException

我正在使用Sears.com的订单源,并使用VS 2013专业版中的Entity Framework 5将订单数据添加到Oracle数据库中。一切按预期工作,直到订单号835,此时它会引发异常。

调用InvalidOperationException会引发SaveChanges()。只有在根据InvalidOperationException类处理了上下文时才应抛出dbContext

//
// Summary:
//     Saves all changes made in this context to the underlying database.
//
// Returns:
//     The number of objects written to the underlying database.
//
// Exceptions:
//   System.InvalidOperationException:
//     Thrown if the context has been disposed.
public virtual int SaveChanges();

我的代码设置如下:

using (Entities rds = new Entities())
{
    foreach (poresponsePurchaseorder po in newSears.purchaseorder)
    {           
            var searsOrders = new SEARS_COM_ORDERS();
            searsOrders.ORDER_CONFIRMATION_NUMBER = po.customerorderconfirmationnumber.ToString() ?? "missing data";
            searsOrders.CUSTOMER_EMAIL = po.customeremail ?? "missing data";
            ...
            rds.SEARS_COM_ORDERS.Add(searsOrders);
            foreach (poresponsePurchaseorderPoline poLine in po.poline)
            {
                var searsOrderItems = new SEARS_COM_ORDER_ITEMS();
                searsOrderItems.PO_NUMBER = (int)po.ponumber;
                searsOrderItems.LINE_NUMBER = (int)poLine.polineheader.linenumber;
                ...
                rds.SEARS_COM_ORDER_ITEMS.Add(searsOrderItems);
            }
            ...
        try
        {                        
            int y = rds.SaveChanges();
            Console.WriteLine(y + " Records added");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
            Console.ReadKey();
        }
    }
}

Entities的调用不是在其他任何地方进行的,也不是Dispose();在任何时候都被调用(除了在using语句终止期间的隐式调用)

例外是:

System.InvalidOperationException: The changes to the database were committed successfully, but an error occurred while updating the object context. Th
e ObjectContext might be in an inconsistent state. Inner exception message: AcceptChanges cannot continue because the object's key values conflict wit
h another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.
   at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
   at System.Data.Entity.Internal.InternalContext.SaveChanges()
   at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
   at System.Data.Entity.DbContext.SaveChanges()
   at MarketplaceIntegrator.Utilities.Marketplaces.SearsCom.SearsTests.GetSearsOrders(String from, String to) in c:\Users\roberth\Programming_Projects
\VisualStudio\vsOnline\MarketplaceIntegrator\Utilities\Marketplaces\SearsCom\SearsTests.cs:line 201

有什么想法吗?

- 编辑 -

似乎我的数据库模型引用了数据库初始开发期间使用的旧主键,从数据库更新模型导致将奇怪的混合主键集添加到模型本身。

我的订单商品表和订单表上唯一的主键应该是ID,它会通过序列自动递增。除了订单商品表上的ID以及订单表中的PO_NUMBER和ID之外,模型还添加了PO_NUMBER和LINE_NUMBER,如edmx所示:

 <EntityType Name="SEARS_COM_ORDER_ITEMS">
          <Key>
            <PropertyRef Name="ID" />
          </Key>
  <EntityType Name="SEARS_COM_ORDERS">
          <Key>
            <PropertyRef Name="ID" />
          </Key>

但是在SSDL中它正确地列出了键。

enter image description here

更改后重新运行程序会导致以下错误。所以现在问题变成了**为什么EDMX显示的数据与底层SSDL不同并触发新的错误? **

新例外:

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.Data.MappingException:
RDS.msl(80,10) : error 3002: Problem in mapping fragments starting at line 80:Potential runtime violation of table SEARS_COM_ORDER_ITEMS's keys (SEARS
_COM_ORDER_ITEMS.ID): Columns (SEARS_COM_ORDER_ITEMS.ID) are mapped to EntitySet SEARS_COM_ORDER_ITEMS's properties (SEARS_COM_ORDER_ITEMS.ID) on the
conceptual side but they do not form the EntitySet's key properties (SEARS_COM_ORDER_ITEMS.ID, SEARS_COM_ORDER_ITEMS.LINE_NUMBER, SEARS_COM_ORDER_ITEM
S.PO_NUMBER).

RDS.msl(97,10) : error 3002: Problem in mapping fragments starting at line 97:Potential runtime violation of table SEARS_COM_ORDERS's keys (SEARS_COM_
ORDERS.ID): Columns (SEARS_COM_ORDERS.ID) are mapped to EntitySet SEARS_COM_ORDERS's properties (SEARS_COM_ORDERS.ID) on the conceptual side but they
do not form the EntitySet's key properties (SEARS_COM_ORDERS.ID, SEARS_COM_ORDERS.PO_NUMBER).

   at System.Data.Mapping.StorageMappingItemCollection.ViewDictionary.SerializedGenerateViews(StorageEntityContainerMapping entityContainerMap, Dictio
nary`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, StorageMappi
ngItemCollection 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, F
unc`2 evaluate, TArg arg)
   at System.Data.Mapping.Update.Internal.ViewLoader.SyncContains[T_Element](EntitySetBase entitySetBase, MetadataWorkspace workspace, Set`1 set, T_El
ement 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, IExtendedDataRec
ord 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 MarketplaceIntegrator.Utilities.Marketplaces.SearsCom.SearsTests.GetSearsOrders(String from, String to) in c:\Users\roberth\Programming_Projects
\VisualStudio\vsOnline\MarketplaceIntegrator\Utilities\Marketplaces\SearsCom\SearsTests.cs:line 200

- 编辑2--

进一步的研究似乎需要手动编辑edmx:

per Microsoft

  

概念模型仅针对添加到数据库的对象进行更新。必须手动进行概念模型的所有其他更改。

手动更改引用字段的属性以将实体键设置为false,这使我再次回到原始错误。

1 个答案:

答案 0 :(得分:3)

对此的实际修复包含多个项目。在我的情况下,以下引起了错误:

在生成模型后更改数据库中的主键。

如果发生这种情况,则需要采取以下步骤来纠正此问题:

  • 从数据库更新模型
  • 通过删除旧引用(在属性上将Entity Key设置为false并将StoreGeneratedPattern更改为none
  • 来修复edmx上的主键
  • 确保新密钥的Entity Key设置为trueStoreGeneratedPattern设置为Identity
  • 通过右键单击edmx并使用文本编辑器选择打开并根据需要编辑以显示正确的密钥,在SSDL上验证信息是否正确。特别是在错误的密钥上查找StoreGeneratedPattern="Identity"并将其移至右侧密钥(如果尚未存在)。 SSDL应该镜像EDMX模型,并且在更新先前项目之后的错误可能意味着SSDL 与模型不同

这个例外是误导性的,至少可以说SaveChanges()调用的文档表明它在dbContext关闭时被抛出,而错误消息表示当都不是实际上是正确的(据我所知,无论如何)。

我知道这篇文章很长,但希望它可以帮助别人解决同样的问题。