3

EFは、特に非常に単純なCRUDの観点からは理解できたと思いましたが、間違っている可能性があります。

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

VatCode 1--* VatRate

これらのエンティティをCRUDするための機能を提供したいと思います。これはWPFアプリケーションにあり、DB接続を不必要に開いたままにしないという点で「切断」されて動作しています。私はデータベースアクセスのイン/アウト方法を好みます。これは、次の統合テストで示されます。

    [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のAttach()メソッドを呼び出すと、次のメソッド本体があります。

    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には、タイプ'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実装が明らかに存在するため、可能である必要があります。

4

1 に答える 1

12

状態を変更するにはエンティティをに追加する必要があるため、Attachとの行を入れ替えます。ChangeObjectStateObjectStateManager

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

    _objectSet.Attach(entity);
    _context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);        
}
于 2012-05-03T14:19:38.690 に答える