2012-05-03 11 views
3

私はEFを理解していると思っていました。特に、簡単にわかりやすくCRUDの観点から考えましたが、間違っている可能性があります。ObjectStateManagerにはオブジェクトへの参照を含むObjectStateEntryが含まれていません

私はObjectContext/Repositoryパターンを持っています。この場合、VatRatesのコレクションを持つVatCodeエンティティがあります。

VatCode 1 - * VatRate

私はこれらのエンティティをCRUDingする機能を提供します。これはWPFアプリケーション内にあり、DB接続を不必要に開いていないという意味で「切断」されています。私はデータベースアクセスの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); 
     } 

     // 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); 
     } 
    } 

コードは単純です。既知の既存のエンティティを取得し、vatCodeに割り当てます。このエンティティは、UIのViewModelで渡され、再度保存されます。このテストでは、私は新しいコンテキストを開くことでこれを混乱させます。これは私がUIでやる方法とまったく同じですので、ここでそれを証明しています。

ただし、以下のメソッド本体を持っているvatRepository、のアタッチ()メソッドを呼び出すには:

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はユーザーコード
メッセージによって未処理であった= ObjectStateManagerタイプのオブジェクトのMac.Sop.Core.Data.VatCode」を参照してObjectStateEntry を含んでいません。

私は多分EFモデルの私のXMLが正しくなかったことを考慮しなかった

(「Mac.Sop.Core.Data.VatCode」への参照を考慮して)、私はすべての問題を見つけることができない、それを通して見て、これらのエンティティは続きます私の他の主体と同様のパターン。

更新: マイEFモデル。私は「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> 

これは、この切断方法で作業する必要があり、それがこのパターンのWCF/ASP.NETの実装として可能でなければなりません明らかに存在する!

答えて

12

ステートを変更するには、ObjectStateManagerにエンティティを追加する必要があるため、AttachChangeObjectState行を入れ替えます。

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

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

ブリリアント!ありがとうございました。木の木、そしてそのすべて。私の愚かな誤り。私は私の鍵を手渡すだろう;)それの美しさは、後世のためにここにいる可能性があるということです。 –

関連する問題