ObjectStateManager不包含具有对象引用的ObjectStateEntry [英] The ObjectStateManager does not contain an ObjectStateEntry with a reference to an object

查看:173
本文介绍了ObjectStateManager不包含具有对象引用的ObjectStateEntry的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以为我理解了EF,特别是在排除简单的CRUD方面,但是我可能错了。



我有一个ObjectContext / Repository模式,在这种情况下一个具有VatRates集合的VatCode实体。



VatCode 1 - * VatRate



我想提供CRUDing这些实体的功能。这是在一个WPF应用程序,并且正在运行断开连接,因为我没有持有数据库连接不专门打开。我更喜欢数据库访问的in /​​ out方法。这在以下集成测试中显示:

  [TestMethod()] 
public void AddVatRateAndSaveVatCodeTest()
{
VatCode vatCode = null;
DateTime expectedDateFrom = DateTime.Now.AddDays(1).Date;
using(SopEntities sopEntities = EntitiesFactory.Create(Properties.Resources.ConnectionString))
{
VatRepository target = new VatRepository(sopEntities);
vatCode = target.SingleOrDefault(q => q.Key ==X4);
Assert.IsNotNull(vatCode);


//模仿离线编辑/断开

使用(SopEntities sopEntities = EntitiesFactory.Create(Properties.Resources.ConnectionString))
{
VatRepository target = new VatRepository(sopEntities);


vatCode.VatRates.Add(new VatRate()
{
DateFrom = expectedDateFrom,
Rate = 20
});
target.Attach(vatCode);
target.SaveChanges();
}

using(SopEntities sopEntities = EntitiesFactory.Create(Properties.Resources.ConnectionString))
{
VatRepository vatRepository = new VatRepository(sopEntities);
VatCode actual = vatRepository.SingleOrDefault(q => q.Key ==X3);
Assert.IsNotNull(actual);
Assert.AreEqual(vatCode.VatRates.Count,actual.VatRates.Count);
Assert.AreEqual(expectedDateFrom,actual.VatRates.OrderBy(q => q.DateFrom).Last()。DateFrom);
}
}

代码很简单。它检索已知的现有实体并将其分配给vatCode。然后,该实体在UI上的ViewModel中传递,并重新保存。在这个测试中,我通过打开一个新的上下文来模拟这个。这是我在UI中的原因,所以我在这里证明。



然而,在调用vatRepository的Attach()方法时,它具有以下方法body:

  public void Attach(TEntity entity)
{
if(entity == null)
throw new ArgumentNullException(entity);

_context.ObjectStateManager.ChangeObjectState(entity,System.Data.EntityState.Modified); // exception here
_objectSet.Attach(entity);
}

我在ChangeObjectState方法中得到下面的异常(我称之为因为实体与原始上下文范围断开连接)


用户代码未处理System.InvalidOperationException

Message = ObjectStateManager不包含ObjectStateEntry
,引用了一个类型为Mac.Sop.Core.Data.VatCode的对象。


我确实认为在EF模型中我的XML可能不正确(考虑参考Mac.Sop.Core.Data。 VatCode'),但是通过它看,我找不到任何问题,这些实体跟我的其他实体相似。



更新:
我的EF模型。我找不到任何Mac.Sop.Core.Data.VatCode的引用:

 <?xml version = 1.0encoding =utf-8?> 
< edmx:Edmx Version =2.0xmlns:edmx =http://schemas.microsoft.com/ado/2008/10/edmx>
< edmx:运行时>
< edmx:StorageModels>
< Schema Namespace =Model.StoreAlias =SelfProvider =System.Data.SqlClientProviderManifestToken =2008xmlns:store =http://schemas.microsoft.com/ado/ 2007/12 / edm / EntityStoreSchemaGeneratorxmlns =http://schemas.microsoft.com/ado/2009/02/edm/ssdl>
< EntityContainer Name =ModelStoreContainer>
< EntitySet Name =MacsSop_VATCodeEntityType =Model.Store.MacsSop_VATCodestore:Type =TablesSchema =dbo/>
< EntitySet Name =MacsSop_VATRateEntityType =Model.Store.MacsSop_VATRatestore:Type =TablesSchema =dbo/>
< AssociationSet Name =FK_MacsSop_VATRate_MacsSop_VATCodeAssociation =Model.Store.FK_MacsSop_VATRate_MacsSop_VATCode>
< End Role =MacsSop_VATCodeEntitySet =MacsSop_VATCode/>
< End Role =MacsSop_VATRateEntitySet =MacsSop_VATRate/>
< / AssociationSet>
< / EntityContainer>
< EntityType Name =MacsSop_VATCode>
< Key>
< PropertyRef Name =Key/>
< / Key>
< Property Name =KeyType =varcharNullable =falseMaxLength =3/>
< Property Name =NameType =nvarcharNullable =falseMaxLength =128/>
< / EntityType>
< EntityType Name =MacsSop_VATRate>
< Key>
< PropertyRef Name =ID/>
< / Key>
< Property Name =IDType =intNullable =falseStoreGeneratedPattern =Identity/>
< Property Name =KeyType =varcharNullable =falseMaxLength =3/>
< Property Name =DateFromType =datetimeNullable =false/>
< Property Name =RateType =decimalNullable =falseScale =2/>
< / EntityType>
<关联名称=FK_MacsSop_VATRate_MacsSop_VATCode>
< End Role =MacsSop_VATCodeType =Model.Store.MacsSop_VATCodeMultiplicity =1/>
< End Role =MacsSop_VATRateType =Model.Store.MacsSop_VATRateMultiplicity =*/>
<参考证明>
< Principal Role =MacsSop_VATCode>
< PropertyRef Name =Key/>
< / Principal>
<从属角色=MacsSop_VATRate>
< PropertyRef Name =Key/>
< / Dependent>
< / ReferentialConstraint>
< / Association>
< / Schema>< / edmx:StorageModels>
<! - CSDL内容 - >
< edmx:ConceptualModels>
< Schema Namespace =ModelAlias =Selfxmlns:annotation =http://schemas.microsoft.com/ado/2009/02/edm/annotationxmlns =http:// schemas .microsoft.com / ADO / 2008/09 / EDM>
< EntityContainer Name =SopEntities注释:LazyLoadingEnabled =true>
< EntitySet Name =VatCodesEntityType =Model.VatCode/>
< EntitySet Name =VatRatesEntityType =Model.VatRate/>
< AssociationSet Name =FK_MacsSop_VATRate_MacsSop_VATCodeAssociation =Model.FK_MacsSop_VATRate_MacsSop_VATCode>
< End Role =MacsSop_VATCodeEntitySet =VatCodes/>
< End Role =MacsSop_VATRateEntitySet =VatRates/>
< / AssociationSet>
< / EntityContainer>
< EntityType Name =VatCode>
< Key>
< PropertyRef Name =Key/>
< / Key>
< Property Type =StringName =KeyNullable =falseMaxLength =3FixedLength =falseUnicode =false/>
< Property Type =StringName =NameNullable =falseMaxLength =128FixedLength =falseUnicode =true/>
< NavigationProperty Name =VatRatesRelationship =Model.FK_MacsSop_VATRate_MacsSop_VATCodeFromRole =MacsSop_VATCodeToRole =MacsSop_VATRate/>
< / EntityType>
< EntityType Name =VatRate>
< Key>
< PropertyRef Name =ID/>
< / Key>
<属性类型=Int32Name =IDNullable =false注释:StoreGeneratedPattern =Identity/>
< Property Type =StringName =KeyNullable =falseMaxLength =3FixedLength =falseUnicode =false/>
< Property Type =DateTimeName =DateFromNullable =false/>
< Property Type =DecimalName =RateNullable =falsePrecision =18Scale =2/>
< NavigationProperty Name =VatCodeRelationship =Model.FK_MacsSop_VATRate_MacsSop_VATCodeFromRole =MacsSop_VATRateToRole =MacsSop_VATCode/>
< / EntityType>
<关联名称=FK_MacsSop_VATRate_MacsSop_VATCode>
< End Type =Model.VatCodeRole =MacsSop_VATCodeMultiplicity =1/>
< End Type =Model.VatRateRole =MacsSop_VATRateMultiplicity =*/>
<参考证明>
< Principal Role =MacsSop_VATCode>
< PropertyRef Name =Key/>
< / Principal>
<从属角色=MacsSop_VATRate>
< PropertyRef Name =Key/>
< / Dependent>
< / ReferentialConstraint>
< / Association>
< / Schema>
< / edmx:ConceptualModels>
<! - C-S映射内容 - >
< edmx:映射>
< Mapping Space =C-Sxmlns =http://schemas.microsoft.com/ado/2008/09/mapping/cs>
< EntityContainerMapping StorageEntityContainer =ModelStoreContainerCdmEntityContainer =SopEntities>
< EntitySetMapping Name =VatCodes>
< EntityTypeMapping TypeName =Model.VatCode>
< MappingFragment StoreEntitySet =MacsSop_VATCode>
< ScalarProperty Name =NameColumnName =Name/>
< ScalarProperty Name =KeyColumnName =Key/>
< / MappingFragment>
< / EntityTypeMapping>
< / EntitySetMapping>
< EntitySetMapping Name =VatRates>
< EntityTypeMapping TypeName =Model.VatRate>
< MappingFragment StoreEntitySet =MacsSop_VATRate>
< ScalarProperty Name =RateColumnName =Rate/>
< ScalarProperty Name =DateFromColumnName =DateFrom/>
< ScalarProperty Name =KeyColumnName =Key/>
< ScalarProperty Name =IDColumnName =ID/>
< / MappingFragment>
< / EntityTypeMapping>
< / EntitySetMapping>
< / EntityContainerMapping>
< / Mapping>
< / edmx:映射>
< / edmx:Runtime>

< / edmx:Edmx>

这需要以这种断开连接的方式工作,它必须是可能的,因为WCF / ASP.NET实现这种模式显然存在!

解决方案

交换附加 ChangeObjectState lines,因为您需要将实体添加到 ObjectStateManager 以更改状态。

  public void Attach(TEntity entity)
{
if(entity == null)
throw new ArgumentNullException(entity) ;

_objectSet.Attach(entity);
_context.ObjectStateManager.ChangeObjectState(entity,EntityState.Modified);
}


I thought I understood EF, particularly in terms of excrutiatingly simple CRUD, but I may be wrong.

I have an ObjectContext/Repository pattern, and in this case a VatCode entity which has a collection of VatRates.

VatCode 1--* VatRate

I want to provide the functionality for CRUDing these entities. This is in a WPF application, and is operating "disconnected" in that I am not holding DB connections open unnecassarily. I prefer the in/out method of database access. This is shown in the following integration test:

    [TestMethod()]
    public void AddVatRateAndSaveVatCodeTest()
    {
        VatCode vatCode=null;
        DateTime expectedDateFrom = DateTime.Now.AddDays(1).Date;
        using (SopEntities sopEntities = EntitiesFactory.Create(Properties.Resources.ConnectionString))
        {
            VatRepository target = new VatRepository(sopEntities);
            vatCode = target.SingleOrDefault(q => q.Key == "X4");
            Assert.IsNotNull(vatCode);
        }

        // mimick offline editing/disconnect

        using (SopEntities sopEntities = EntitiesFactory.Create(Properties.Resources.ConnectionString))
        {
            VatRepository target = new VatRepository(sopEntities);


            vatCode.VatRates.Add(new VatRate()
                {
                    DateFrom=expectedDateFrom,
                    Rate=20
                });
            target.Attach(vatCode);
            target.SaveChanges();
        }

        using (SopEntities sopEntities=EntitiesFactory.Create(Properties.Resources.ConnectionString))
        {
            VatRepository vatRepository=new VatRepository(sopEntities);
            VatCode actual=vatRepository.SingleOrDefault(q=>q.Key=="X3");
            Assert.IsNotNull(actual);
            Assert.AreEqual(vatCode.VatRates.Count,actual.VatRates.Count);
            Assert.AreEqual(expectedDateFrom,actual.VatRates.OrderBy(q=>q.DateFrom).Last().DateFrom);
        }
    }

The code is simple. It retrieves a known existing entity and assigns it to vatCode. This entity is then passed around in the ViewModel on the UI, and re-saved. In this test, I mimmick this by opening a new context. This is exactly how I would in the UI, so I am proving it here.

However, on calling the Attach() method of the vatRepository, which has the following method body:

    public void Attach(TEntity entity)
    {
        if (entity == null)
            throw new ArgumentNullException("entity");

        _context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified); // exception here
        _objectSet.Attach(entity);
    }

I get the exception below on the ChangeObjectState method (which I call because the entity was disconnected from the original context scope).

System.InvalidOperationException was unhandled by user code
Message=The ObjectStateManager does not contain an ObjectStateEntry with a reference to an object of type 'Mac.Sop.Core.Data.VatCode'.

I did consider that maybe my XML in the EF model was not correct (considering reference to 'Mac.Sop.Core.Data.VatCode'), but looking through it I cannot find any issues and these entities follow similar patterns with my other entities.

Update: My EF model. I can't find any reference to 'Mac.Sop.Core.Data.VatCode':

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
  <edmx:Runtime>
    <edmx:StorageModels>
    <Schema Namespace="Model.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
        <EntityContainer Name="ModelStoreContainer">
          <EntitySet Name="MacsSop_VATCode" EntityType="Model.Store.MacsSop_VATCode" store:Type="Tables" Schema="dbo" />
          <EntitySet Name="MacsSop_VATRate" EntityType="Model.Store.MacsSop_VATRate" store:Type="Tables" Schema="dbo" />
          <AssociationSet Name="FK_MacsSop_VATRate_MacsSop_VATCode" Association="Model.Store.FK_MacsSop_VATRate_MacsSop_VATCode">
            <End Role="MacsSop_VATCode" EntitySet="MacsSop_VATCode" />
            <End Role="MacsSop_VATRate" EntitySet="MacsSop_VATRate" />
          </AssociationSet>
        </EntityContainer>
        <EntityType Name="MacsSop_VATCode">
          <Key>
            <PropertyRef Name="Key" />
          </Key>
          <Property Name="Key" Type="varchar" Nullable="false" MaxLength="3" />
          <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="128" />
        </EntityType>
        <EntityType Name="MacsSop_VATRate">
          <Key>
            <PropertyRef Name="ID" />
          </Key>
          <Property Name="ID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
          <Property Name="Key" Type="varchar" Nullable="false" MaxLength="3" />
          <Property Name="DateFrom" Type="datetime" Nullable="false" />
          <Property Name="Rate" Type="decimal" Nullable="false" Scale="2" />
        </EntityType>
        <Association Name="FK_MacsSop_VATRate_MacsSop_VATCode">
          <End Role="MacsSop_VATCode" Type="Model.Store.MacsSop_VATCode" Multiplicity="1" />
          <End Role="MacsSop_VATRate" Type="Model.Store.MacsSop_VATRate" Multiplicity="*" />
          <ReferentialConstraint>
            <Principal Role="MacsSop_VATCode">
              <PropertyRef Name="Key" />
            </Principal>
            <Dependent Role="MacsSop_VATRate">
              <PropertyRef Name="Key" />
            </Dependent>
          </ReferentialConstraint>
        </Association>
      </Schema></edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema Namespace="Model" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
        <EntityContainer Name="SopEntities" annotation:LazyLoadingEnabled="true" >
          <EntitySet Name="VatCodes" EntityType="Model.VatCode" />
          <EntitySet Name="VatRates" EntityType="Model.VatRate" />
          <AssociationSet Name="FK_MacsSop_VATRate_MacsSop_VATCode" Association="Model.FK_MacsSop_VATRate_MacsSop_VATCode">
            <End Role="MacsSop_VATCode" EntitySet="VatCodes" />
            <End Role="MacsSop_VATRate" EntitySet="VatRates" />
          </AssociationSet>
        </EntityContainer>
        <EntityType Name="VatCode">
          <Key>
            <PropertyRef Name="Key" />
          </Key>
          <Property Type="String" Name="Key" Nullable="false" MaxLength="3" FixedLength="false" Unicode="false" />
          <Property Type="String" Name="Name" Nullable="false" MaxLength="128" FixedLength="false" Unicode="true" />
          <NavigationProperty Name="VatRates" Relationship="Model.FK_MacsSop_VATRate_MacsSop_VATCode" FromRole="MacsSop_VATCode" ToRole="MacsSop_VATRate" />
        </EntityType>
        <EntityType Name="VatRate">
          <Key>
            <PropertyRef Name="ID" />
          </Key>
          <Property Type="Int32" Name="ID" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
          <Property Type="String" Name="Key" Nullable="false" MaxLength="3" FixedLength="false" Unicode="false" />
          <Property Type="DateTime" Name="DateFrom" Nullable="false" />
          <Property Type="Decimal" Name="Rate" Nullable="false" Precision="18" Scale="2" />
          <NavigationProperty Name="VatCode" Relationship="Model.FK_MacsSop_VATRate_MacsSop_VATCode" FromRole="MacsSop_VATRate" ToRole="MacsSop_VATCode" />
        </EntityType>
        <Association Name="FK_MacsSop_VATRate_MacsSop_VATCode">
          <End Type="Model.VatCode" Role="MacsSop_VATCode" Multiplicity="1" />
          <End Type="Model.VatRate" Role="MacsSop_VATRate" Multiplicity="*" />
          <ReferentialConstraint>
            <Principal Role="MacsSop_VATCode">
              <PropertyRef Name="Key" />
            </Principal>
            <Dependent Role="MacsSop_VATRate">
              <PropertyRef Name="Key" />
            </Dependent>
          </ReferentialConstraint>
        </Association>
      </Schema>
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
      <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
        <EntityContainerMapping StorageEntityContainer="ModelStoreContainer" CdmEntityContainer="SopEntities" >
          <EntitySetMapping Name="VatCodes">
            <EntityTypeMapping TypeName="Model.VatCode">
              <MappingFragment StoreEntitySet="MacsSop_VATCode">
                <ScalarProperty Name="Name" ColumnName="Name" />
                <ScalarProperty Name="Key" ColumnName="Key" />
              </MappingFragment>
            </EntityTypeMapping>
          </EntitySetMapping>
          <EntitySetMapping Name="VatRates">
            <EntityTypeMapping TypeName="Model.VatRate">
              <MappingFragment StoreEntitySet="MacsSop_VATRate">
                <ScalarProperty Name="Rate" ColumnName="Rate" />
                <ScalarProperty Name="DateFrom" ColumnName="DateFrom" />
                <ScalarProperty Name="Key" ColumnName="Key" />
                <ScalarProperty Name="ID" ColumnName="ID" />
              </MappingFragment>
            </EntityTypeMapping>
          </EntitySetMapping>
        </EntityContainerMapping>
      </Mapping>
    </edmx:Mappings>
  </edmx:Runtime>

</edmx:Edmx>

This needs to work in this disconnected fashion and it must be possible as WCF/ASP.NET implementations of this pattern obviously exist!

解决方案

Swap the Attach and ChangeObjectState lines because you need to add the entity to ObjectStateManager in order to change the state.

public void Attach(TEntity entity)
{
    if (entity == null)
        throw new ArgumentNullException("entity");

    _objectSet.Attach(entity);
    _context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);        
}

这篇关于ObjectStateManager不包含具有对象引用的ObjectStateEntry的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆