Why am I getting an InvalidOperationException
when adding orders to an Oracle 11gR2 Database using EF 5?
I'm consuming an order feed from Sears.com and adding the order data into an Oracle database using Entity Framework 5 from within VS 2013 professional. Everything works as expected up to order number 835 at which point it throws an exception.
The InvalidOperationException
gets thrown by a call to SaveChanges()
. The InvalidOperationException
should only be thrown if the context has been disposed per the dbContext
class:
//
// 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();
My code is setup as follows:
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();
}
}
}
a call to Entities
is not made anywhere else, nor is Dispose();
called at any time (aside from the implicit call during the termination of the using
statement)
The exception is:
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
Any ideas?
--Edit--
It seems my database model was referencing old primary keys used during the initial development of the database, updating the model from the database resulted in a weird hybrid set of primary keys being added to the model itself.
The only primary key on both my order items table as well as the orders table should be ID, which is auto incremented via a sequence. The model instead added PO_NUMBER and LINE_NUMBER in addition to ID on the order items table and PO_NUMBER and ID to the orders table as shown on the edmx:
<EntityType Name="SEARS_COM_ORDER_ITEMS">
<Key>
<PropertyRef Name="ID" />
</Key>
<EntityType Name="SEARS_COM_ORDERS">
<Key>
<PropertyRef Name="ID" />
</Key>
however in the SSDL it correctly lists the keys.
Rerunning the program after the changes results in the following error. So now the question becomes **Why does the EDMX show different data than the underlaying SSDL and trigger a new error? **
New 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.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
--Edit 2--
Further research appears to require manual editing of the edmx:
per Microsoft:
The conceptual model will be updated only for objects that are added to the database. All other changes to the conceptual model must be made manually.
Manually changing the properties for the referenced fields to set entity key to false as brought me back to the original error again.