locked
WCF RIAサービスで子エンティティのデータ削除でエラーになる RRS feed

  • 質問

  • WCF RIAサービスで子エンティティを含むデータを取得してその子エンティティを削除して更新しようとするとエラーになり解決策を模索しております。

    参考ソースでは子エンティティを直接削除しておりますが、実際のところ子エンティティ群をDataGridで編集するようなことになります。

    解決方法についてよろしくご教授のほどお願いいたします。

    	// ---- メタデータinternal sealed class CountryMetadata
            {
                // メタデータ クラスはインスタンス化するためのものではありません。
                private CountryMetadata()
                {
                }            
    
                public Guid ID { get; set; }
                
                public string Name { get; set; }
    
                [Include]
                //[Composition]
                public EntityCollection<Preference> Preferences { get; set; }
            }
            
            ~
            	
            internal sealed class PreferenceMetadata
            {
                // メタデータ クラスはインスタンス化するためのものではありません。
                private PreferenceMetadata()
                {
                }            
    
                public Guid ID { get; set; }
                
                public string Name { get; set; }
            }
            
            // ---- ドメインサービス
            public IQueryable<Country> GetCountrys()
            {
                return this.ObjectContext.Countrys.Include("Preferences");
            }
            
            public void UpdateCountry(CountrycurrentCountry)
            {
                this.ObjectContext.Countrys.AttachAsModified(currentCountry this.ChangeSet.GetOriginal(currentCountry));
                // System.ArgumentNullException はユーザー コードによってハンドルされませんでした。
            }
            
            public void UpdatePreference(Preference currentPreference)
            {
                this.ObjectContext.Preferences.AttachAsModified(currentPreference this.ChangeSet.GetOriginal(currentPreference));
                // 
            }
            
            // ----------------
            
    
            private void btnCommit_Click(object sender, RoutedEventArgs e)
            {
            	// データは次のような構成になっている
            	// Countory:日本
            	// Preferences:東京、大阪
           		
           		// Composition属性がないとき
            	// Countrysエンティティを取得したときcontextはCountrysとPreferencesのエンティティを取得している。
            	// this.context.Countrysのエンティティ(日本)の中のPreferencesのエンティティ(東京)は削除されている。
            	// this.context.Preferencesのエンティティ(東京)は削除されておらず更新になっている。
            	// SubmitChangeするとドメインサービスのUpdatePreferenceメソッドが実行されエラーになる。
            
            	// Composition属性があるとき
            	// Countrysエンティティを取得したときcontextはCountrysのエンティティを取得している。
            	// this.context.Countrysのエンティティ(日本)の中のPreferencesのエンティティ(東京)は削除されている。
            	// SubmitChangeするとドメインサービスのUpdateCountryメソッドが実行されエラーになる。
            	
            	// なお、Preferenceのエンティティの追加、修正は問題ない
            	
    			foreach (Country country in this.context.Countrys)
                {
                	foreach (Preference preference in country.Preferences)
                	{
                		// 削除はSubmitChangeすると問題になる
                		if (preference.Name == "東京")
                			country.Preferences.Remove(preference);
                		
                		// 変更はSumbitChangeしても問題ない
                		//if (preference.Name == "大阪")
                		//	preference.Name = "北海道";
                    }
    
                	// 追加はSumbitChangeしても問題ない                
                    //Preference pref = new Preference();
                    //pref.ID = Guid.NewID();
                    //pref.Name = "愛知";
                    //country.Preferences.Add(pref);
                    
                 }
                    
                this.context.SubmitChanges(OnSubmitCompleted, null);
            }
    


    2011年10月28日 5:02

回答

  • Composition属性を使用したい場合は、親のサービスメソッドを書き換えないといけなかったと思います。
    (参考:■合成階層 http://msdn.microsoft.com/ja-jp/library/ee707346(v=vs.91).aspx


    Composition属性を使用しない実装とするなら

    
        // 削除はSubmitChangeすると問題になる
        if (preference.Name == "東京")
            country.Preferences.Remove(preference);
    


    こいつが間違っているんじゃないかと思います。


    context.Preferences.Remove(preference);
    


    のようにDomainContextのエンティティセットから削除する必要があったかと。

    2011年10月30日 16:00

すべての返信

  • Composition属性を使用したい場合は、親のサービスメソッドを書き換えないといけなかったと思います。
    (参考:■合成階層 http://msdn.microsoft.com/ja-jp/library/ee707346(v=vs.91).aspx


    Composition属性を使用しない実装とするなら

    
        // 削除はSubmitChangeすると問題になる
        if (preference.Name == "東京")
            country.Preferences.Remove(preference);
    


    こいつが間違っているんじゃないかと思います。


    context.Preferences.Remove(preference);
    


    のようにDomainContextのエンティティセットから削除する必要があったかと。

    2011年10月30日 16:00
  • ご返信ありがとうございます。

    最初に前提として書き忘れていましたが、サンプルのようにCountry単位でPrefrerenceを編集したい前提がございます。

    たとえばPreferenceに東京、大阪、ニューヨーク、ニュージーランドなどある場合は日本を選択しているときには東京、大阪など、アメリカを選択しているときはニューヨーク、ニュージーランドなどとPreferenceを同列に編集することはありません。

    Tetsuaki Uchida様のおっしゃられるComposition属性を使用してサービスメソッドの書き換えを行うのがよいのかなと思います。

    Composition属性を使用しない場合として削除したときPreference側のCountryのIDが0値になるのでその特定を活かしてサービスメソッドを書き換える方法も見つけました。ただしこれはサービスメソッドの実装としては簡単にできますが特定状況の下でしか使用できないものであると考えています。

    ありがとうございました。

     

    2011年10月31日 0:22