为什么在使用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中它正确地列出了键。
更改后重新运行程序会导致以下错误。所以现在问题变成了**为什么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,这使我再次回到原始错误。
答案 0 :(得分:3)
对此的实际修复包含多个项目。在我的情况下,以下引起了错误:
在生成模型后更改数据库中的主键。
如果发生这种情况,则需要采取以下步骤来纠正此问题:
Entity Key
设置为false
并将StoreGeneratedPattern
更改为none
)Entity Key
设置为true
,StoreGeneratedPattern
设置为Identity
StoreGeneratedPattern="Identity"
并将其移至右侧密钥(如果尚未存在)。 SSDL应该镜像EDMX模型,并且在更新先前项目之后的错误可能意味着SSDL 与模型不同。 这个例外是误导性的,至少可以说SaveChanges()
调用的文档表明它在dbContext关闭时被抛出,而错误消息表示当都不是实际上是正确的(据我所知,无论如何)。
我知道这篇文章很长,但希望它可以帮助别人解决同样的问题。