2016-02-24 10 views
15

で例外を引き起こしている私は、WCFを使用してオブジェクトを送信しようとしています。オブジェクトはEFを使用してDBから取得されます。は、EFを使用してエンティティを更新し、WCFを使用してそれを送信しようとすると - プロパティが更新シナリオ

これは私が得る例外です:

enter image description here

これが唯一の更新シナリオで発生します。挿入は完全に機能します。バグトラッキング
は、私はこの問題は、私が最近追加された(Travelersと呼ばれる)のコレクションであることがわかりました。ここで

は、私がWCFによって更新されたエンティティを送信する前に、更新した後、実行時にその値を監視しようとすると何が起こるかです:

enter image description here

ここで問題のあるクラスのプロパティの宣言は(だ、私はコメントを外してみましたDataMember属性が、それは動作しませんでした):

[DataContract] 
public class Travel : InsuredObject, ISaleEntity, ICloneable 
{  
    //[DataMember] 
    public virtual ICollection<Traveler> Travelers { get; set; } 
    ... 

私はthis.Configuration.ProxyCreationEnabled = false;および/またはthis.Configuration.LazyLoadingEnabled = false;はそれを修正する可能性があることを読んだが、私は理由のためにそれらを変更することはできません
更新方法:

public virtual TEntity CreateAndUpdate(int saleId, TEntity entity) { 
    var context = ((IObjectContextAdapter)this.Context).ObjectContext; 

    var objBaseSet = context.CreateObjectSet<TBase>(); 

    var entityBaseKey = context.CreateEntityKey(objBaseSet.EntitySet.Name, entity); 
    Object foundBaseEntity; 
    var baseExists = context.TryGetObjectByKey(entityBaseKey, out foundBaseEntity); 

    entity.Id = saleId; 

    if (!baseExists) { 
     this.GetDbSet<TEntity>().Add(entity); 
    } 

    this.objectContext.SaveChanges(); 

    return entity; 
} 

含むオ​​ブジェクトを取得更新する前に: - 私は彼らと一緒に遊んでみたら私を超え、とさえ私は

追加コード他のいくつかの例外を...得た

public virtual IQueryable<TEntity> GetAll(Expression<Func<TEntity, bool>> where, bool brutalRefresh = false) { 

    IQueryable<TEntity> retObj = this.GetDbSet<TEntity>(); 
    if (where != null) { 
     retObj = retObj.Where(where); 
    } 

    if (brutalRefresh) { 
     var context = ((IObjectContextAdapter)this.Context).ObjectContext; 
     context.Refresh(RefreshMode.StoreWins, retObj); 
    } 

    return retObj; 
} 

...すべてのコードは他のプロジェクトと共通のコードで、私と同じエンティティを送受信します。それはちょうどTravelですtity私は

Travelerクラス(完全に)..私は探しているソリューションは、共通のコードで0の変化で構成する必要がありますので、私に問題を引き起こすことを、追加しました:

[DataContract] 
    public class Traveler : ISaleEntity, ICloneable 
    { 
     [DataMember] 
     public int Id { get; set; } 

     [DataMember] 
     public string FirstName { get; set; } 

     [DataMember] 
     public string LastName { get; set; } 

     [DataMember] 
     public string IDNumber { get; set; } 

     [DataMember] 
     public DateTime? BirthDate { get; set; } 

     [DataMember] 
     public virtual ICollection<SelectedCoverage> SelectedCoverages { get; set; } 

     [NotMapped] 
     public List<MedicalQuestionnaireAnswer> MedicalQuestionnaireAnswers 
     { 
      get 
      { 
       if (string.IsNullOrWhiteSpace(DBMedicalQuestionnaireAnswers)) 
        return new List<MedicalQuestionnaireAnswer>(); 

       return DBMedicalQuestionnaireAnswers.Split(',') 
        .Select(c => (MedicalQuestionnaireAnswer)int.Parse(c)).ToList(); 
      } 
      set { DBMedicalQuestionnaireAnswers = string.Join(",", value.Select(m => (int)m)); } 
     } 

     [NotMapped] 
     public Genders Gender 
     { 
      get { return (Genders)DBGender; } 
      set { DBGender = (int)value; } 
     } 

     /// <summary> 
     /// NOTE! Do not use this property directly! use MedicalQuestionnaireAnswers instead 
     /// </summary> 
     [DataMember] 
     public string DBMedicalQuestionnaireAnswers { get; set; } 

     /// <summary> 
     /// NOTE! Do not use this property directly! use Gender instead 
     /// </summary> 
     [DataMember] 
     public int DBGender { get; set; } 

     public object Clone() 
     { 
      Traveler traveler = new Traveler(); 
      traveler.FirstName = this.FirstName; 
      traveler.LastName = this.LastName; 
      traveler.IDNumber = this.IDNumber; 
      traveler.BirthDate = this.BirthDate; 
      traveler.DBMedicalQuestionnaireAnswers = this.DBMedicalQuestionnaireAnswers; 
      traveler.Gender = this.Gender; 
      if (this.SelectedCoverages != null) 
      { 
       traveler.SelectedCoverages = this.SelectedCoverages.Select(sc => (SelectedCoverage)sc.Clone()).ToList(); 
      } 

      return traveler; 
     } 
    } 

    public static class TravelerExtension 
    { 

     /// <summary> 
     /// copy all the property except from the id and src defualt values 
     /// </summary> 
     /// <param name="dbTraveler"></param> 
     /// <param name="src"></param> 
     public static void CopyTravelerProperties(this Traveler target, Traveler src) 
     { 
      target.FirstName = src.FirstName; 
      target.LastName = src.LastName; 
      target.IDNumber = src.IDNumber; 
      target.BirthDate = src.BirthDate; 
      target.DBMedicalQuestionnaireAnswers = src.DBMedicalQuestionnaireAnswers; 
      target.DBGender = src.DBGender; 
      target.SelectedCoverages.CopySelectedCoveragesProperties(src.SelectedCoverages); 
     } 
    } 

    public static class TravelersExtension 
    { 

     /// <summary> 
     /// copy all the property except from the id and src defualt values 
     /// </summary> 
     /// <param name="dbTravelers"></param> 
     /// <param name="src"></param> 
     public static void CopyTravelersProperties(this ICollection<Traveler> target, ICollection<Traveler> src) 
     { 

      List<int> allTravelersIdsSrc = src.Select(t => t.Id).ToList(); 

      // remove ids exist target and not in src 
      target.ToList().RemoveAll(t => allTravelersIdsSrc.Contains(t.Id)); 


      target = target ?? new List<Traveler>(); 
      foreach (Traveler srcTraveler in src) 
      { 
       var targetTraveler = target.FirstOrDefault(targetTrv => srcTraveler.Id != 0 && targetTrv.Id == srcTraveler.Id); 
       // if not exist traveler with target traveler id in db 
       if (targetTraveler == null) 
       { 
        // add srcTraveler to target 
        target.Add(srcTraveler); 
       } 
       else 
       { 
        targetTraveler.CopyTravelerProperties(srcTraveler); 
       } 

      } 
     } 
    } 

さらに情報:
前イミディエイトウィンドウで値を取得しようとするToList()を呼び出す場合 イミディエイトウィンドウ例外は発生しません。しかし、問題自体は残る。上[DataMember]属性をコメントしようと

Travelerクラスに

public virtual ICollection<SelectedCoverage> SelectedCoverages { get; set; } 

には影響を与えませんでした。

例外:

enter image description here

さらに情報2:私は上記の[DataMember]を変更すると

public class Quote : ISaleEntity, ICloneable {  
    ... 
     [DataMember] 
     public virtual Travel Travel { get; set; } 
    ... 

例外が発生するだけで1エンティティがあります[IgnoreDataMember] - 例外はありません。

私は[IgnoreDataMember]

[DataContract] 
    public class Travel : InsuredObject, ISaleEntity, ICloneable 
    { 
     [IgnoreDataMember] 
     //[DataMember] 
     public bool? IsFromIsrael { get; set; } 

     [IgnoreDataMember] 
     //[DataMember] 
     public virtual ICollection<Traveler> Travelers { get; set; } 

     [IgnoreDataMember] 
     public virtual Quote Quote { get; set; } 

      [IgnoreDataMember] 
     //[DataMember] 
     [NotMapped] 
     public List<int> DestinationsCodes 
     { 
      get 
      { 
       if (string.IsNullOrWhiteSpace(DBDestinationsCodes)) 
        return new List<int>(); 

       return DBDestinationsCodes.Split(',').Select(c => int.Parse(c)).ToList(); 
      } 

      set { DBDestinationsCodes = string.Join(",", value); } 
     } 

     /// <summary> 
     /// NOTE! Do not use this property directly! use DestinationsCodes instead 
     /// </summary> 
      [IgnoreDataMember] 
     //[DataMember] 
     public string DBDestinationsCodes { get; set; } 
     ... 

に、このクラスのすべてのプロパティを設定するしかし、例外が引き続き発生します。おそらくこのクラスが継承しているクラスのために:

[DataContract] 
    [KnownType(typeof(Vehicle))] 
    [KnownType(typeof(Apartment))] 
    [KnownType(typeof(Travel))] 
    public class InsuredObject : ISaleEntity, ICloneable { 
     [Key] 
     [DataMember] 
     public int Id { get; set; } 

     [DataMember] 
     public int? OwnerTypeId { get; set; } 


     //navigation property 

     [DataMember] 
     public bool? HasShiabud { get; set; } 

     [DataMember] 
     [IgnoreDataMember] 
     public virtual Shiabud Shiabud { get; set; } 

     //[NotMapped] 
     //public virtual Proposal Proposal { get; set; } 

     //[DataMember] 
     [IgnoreDataMember] 
     public virtual ICollection<Coverage> Coverages { get; set; } 
     ... 

このエンティティをWCF経由で送信するにはどうすればよいですか?

+0

保存する前にTravellersで(一時的に)ToList()を呼び出すと、エラーはなくなりますか? – cokeman19

+0

いいえ..同じエラー –

+0

それは好奇心です。一般的に、この問題を扱うアプローチは、@WicherVisser(または代わりに 'Include(...)'、[like here](http://stackoverflow.com/a/19928165/1197605) ToList()を呼び出すことは良いテストです。 'Traveler'クラスも投稿できますか?おそらく、例外を引き起こしている何かがあります。スローされた例外(未処理のものとは対照的に)を破棄し、それ以前に他のものがスローされているかどうかを確認するために、VSオプションを設定することもできます。 – cokeman19

答えて

0

DBの更新を行うEFコンテキストでコードの一部を共有できますか?

エラーメッセージから、トリックを実行しているWCFではないことがわかります。むしろ、変更を適用する時点(SaveChanges()メソッド)までにEF ObjectContentが破棄されているようです。これは、WCFメソッド呼び出し間で有効にしておくと発生します。バックエンドの静的変数として使用し、それをusing節に入れます。

これは、古いバージョンでも同様ですが、EF 6以降のDBコンテキストに遅延ロードを適用するために有効です。あなたの特性は、仮想せることにより

public class DomainDbContext : DbContext 
{ 
    Configuration.LazyLoadingEnabled = false; 
} 
+0

どうもありがとう、私は質問を更新し、そして今、あなたは手段を書いたものすべてを理解しようとしている:) :(。SaveChangesメソッドは、WCFを送信する前に起こっているようです。.. EFの –

+0

バージョンあなたはより多くの文字を必要とする? –

+1

5を使用していますので、私は、私は疑問に適切なタグを使用すると言うでしょう。 –

0

を(私はこれが必要とされないことがあります。構成に対処するために継承されたクラスを実装)、何をやっていることは遅延ロードです。

代わりにICollectionにプロパティを作成し、代わりに読み込みを行うことができます。

関連する問題