2016-11-06 3 views
1

私はこの数日間、この問題に苦労しています。 WebAPI APIと通信するWebアプリケーションがあり、 "Entity Framework Reverse POCO CodeFirst Generator"ビジュアルスタジオ拡張によって作成および維持されるエンティティを取得および更新します。それらはすべてエンティティとDbContextを生成するようです。しかしここに問題があります:Webクライアントは、 "Patient"エンティティを返すAPIメソッドにajax呼び出しを行います。この患者エンティティには、NULLIableとPharmacyIdの2つのヌル入力可能な外部キーがあります。今、患者がリポジトリによって取り出されるとき、それはサーバError screen shot 1の上でよく見えます。 LanguageIdとPharmacyIdは期待通りにnullです。患者のナビゲーションプロパティ、すなわちluLanguageとPharmacyも正しくnullに設定されます。クライアントが受け取ったjsonオブジェクトも今度はError Screen shot 2のように見えます。外部キーIdとナビゲーションプロパティの両方がnullです。クライアントは、患者オブジェクトに対するいくつかのオプションの編集を行い、オブジェクトをサーバーにPOSTして戻します。 POST ajax呼び出しが行われる直前に、患者のjsonオブジェクトはまだ正常に見えます。Error Screen shot 3。外部キーとナビゲーションプロパティはnullです。しかし、そのオブジェクトがWebAPIメソッドによって受信されるとすぐに、不思議なことに空の言語と薬局のナビゲーションプロパティError Screen shot 4があります。外部キーに対応する主キーはINTであるため、0で初期化されます。これにより、言語の外部キーと言語ナビゲーションオブジェクトの主キーが一致しないため、DbContextを更新しようとすると気が狂ってしまいます。 1つはヌルで、もう1つは0(ゼロ)です。私は非常に多くの異なるテストを試みましたが、どのようにカットしても同じ問題に戻ります。EF6がヌル可能な外部キーの空の子エンティティを生成しています

エンティティモデルビルダーの設定コードは次のとおりです。

public PatientConfiguration(string schema) 
    { 
     ToTable("Patient", schema); 
     HasKey(x => x.Id); 

     Property(x => x.Id).HasColumnName(@"ID").IsRequired().HasColumnType("bigint").HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity); 
     Property(x => x.LastName).HasColumnName(@"LastName").IsOptional().IsUnicode(false).HasColumnType("varchar").HasMaxLength(50); 
     Property(x => x.FirstName).HasColumnName(@"FirstName").IsOptional().IsUnicode(false).HasColumnType("varchar").HasMaxLength(50); 
     Property(x => x.MiddleName).HasColumnName(@"MiddleName").IsOptional().IsUnicode(false).HasColumnType("varchar").HasMaxLength(30); 
     Property(x => x.Gender).HasColumnName(@"Gender").IsOptional().IsUnicode(false).HasColumnType("varchar").HasMaxLength(18); 
     Property(x => x.Dob).HasColumnName(@"DOB").IsRequired().HasColumnType("datetime"); 
     Property(x => x.SocialSecurity).HasColumnName(@"SocialSecurity").IsOptional().HasColumnType("varbinary"); 
     Property(x => x.LastFourSsn).HasColumnName(@"LastFourSSN").IsOptional().HasColumnType("int"); 
     Property(x => x.PharmacyId).HasColumnName(@"PharmacyID").IsOptional().HasColumnType("bigint"); 
     Property(x => x.InUseById).HasColumnName(@"InUseByID").IsOptional().HasColumnType("bigint"); 
     Property(x => x.LanguageId).HasColumnName(@"LanguageID").IsOptional().HasColumnType("int"); 
     Property(x => x.Status).HasColumnName(@"Status").IsOptional().IsUnicode(false).HasColumnType("varchar").HasMaxLength(10); 
     Property(x => x.IsInactive).HasColumnName(@"IsInactive").IsRequired().HasColumnType("bit"); 
     Property(x => x.CreatedById).HasColumnName(@"CreatedByID").IsRequired().HasColumnType("bigint"); 
     Property(x => x.CreatedDate).HasColumnName(@"CreatedDate").IsRequired().HasColumnType("datetime"); 
     Property(x => x.UpdatedById).HasColumnName(@"UpdatedByID").IsRequired().HasColumnType("bigint"); 
     Property(x => x.UpdatedDate).HasColumnName(@"UpdatedDate").IsRequired().HasColumnType("datetime"); 
     Property(x => x.MigratedBy).HasColumnName(@"MigratedBy").IsOptional().IsUnicode(false).HasColumnType("varchar").HasMaxLength(10); 
     Property(x => x.TimeStamped).HasColumnName(@"TimeStamped").IsRequired().IsFixedLength().HasColumnType("timestamp").HasMaxLength(8).IsRowVersion().HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Computed); 

     // Foreign keys 
     HasOptional(a => a.LuLanguage).WithMany(b => b.Patients).HasForeignKey(c => c.LanguageId).WillCascadeOnDelete(false); // FK_Patient_luLanguage 
     HasOptional(a => a.Pharmacy).WithMany(b => b.Patients).HasForeignKey(c => c.PharmacyId).WillCascadeOnDelete(false); // FK_Pharmacy_Patient 
     InitializePartial(); 
    } 

そして、ここで生成された患者のエンティティ

ある
public partial class Patient : EntityBase 
{ 
    //[DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public long Id { get; set; } // ID (Primary key) 
    public string LastName { get; set; } // LastName (length: 50) 
    public string FirstName { get; set; } // FirstName (length: 50) 
    public string MiddleName { get; set; } // MiddleName (length: 30) 
    public string Gender { get; set; } // Gender (length: 18) 
    public System.DateTime Dob { get; set; } // DOB 
    public byte[] SocialSecurity { get; set; } // SocialSecurity 
    public int? LastFourSsn { get; set; } // LastFourSSN 
    public long? PharmacyId { get; set; } // PharmacyID 
    public long? InUseById { get; set; } // InUseByID 
    public int? LanguageId { get; set; } // LanguageID 
    public string Status { get; set; } // Status (length: 10) 
    public bool IsInactive { get; set; } // IsInactive 
    public long CreatedById { get; set; } // CreatedByID 
    public System.DateTime CreatedDate { get; set; } // CreatedDate 
    public long UpdatedById { get; set; } // UpdatedByID 
    public System.DateTime UpdatedDate { get; set; } // UpdatedDate 
    public string MigratedBy { get; set; } // MigratedBy (length: 10) 
    public byte[] TimeStamped { get; private set; } // TimeStamped (length: 8) 

    // Reverse navigation 
    public virtual System.Collections.Generic.ICollection<AuditPatientChange> AuditPatientChanges { get; set; } // auditPatientChange.R_88 
    public virtual System.Collections.Generic.ICollection<PatientAddress> PatientAddresses { get; set; } // PatientAddress.FK_PatientAddress_Patient 
    public virtual System.Collections.Generic.ICollection<PatientCallTracking> PatientCallTrackings { get; set; } // PatientCallTracking.R_74 
    public virtual System.Collections.Generic.ICollection<PatientContact> PatientContacts { get; set; } // PatientContact.FK_PatientContact_Patient 
    public virtual System.Collections.Generic.ICollection<PatientCreditCard> PatientCreditCards { get; set; } // PatientCreditCard.R_59 
    public virtual System.Collections.Generic.ICollection<PatientDiseaseState> PatientDiseaseStates { get; set; } // PatientDiseaseState.R_65 
    public virtual System.Collections.Generic.ICollection<PatientIcd10> PatientIcd10 { get; set; } // PatientICD10.R_63 
    public virtual System.Collections.Generic.ICollection<PatientMedicalHistory> PatientMedicalHistories { get; set; } // PatientMedicalHistory.R_60 
    public virtual System.Collections.Generic.ICollection<PatientNoteAndComment> PatientNoteAndComments { get; set; } // PatientNoteAndComment.R_73 
    public virtual System.Collections.Generic.ICollection<PatientPayment> PatientPayments { get; set; } // PatientPayment.R_56 
    public virtual System.Collections.Generic.ICollection<PatientPlanPolicy> PatientPlanPolicies { get; set; } // PatientPlanPolicy.R_90 
    public virtual System.Collections.Generic.ICollection<PatientReferral> PatientReferrals { get; set; } // PatientReferral.FK_PatientReferral_Patient 
    public virtual System.Collections.Generic.ICollection<PatientShareOfCost> PatientShareOfCosts { get; set; } // PatientShareOfCost.R_62 
    public virtual System.Collections.Generic.ICollection<Rx> Rxes { get; set; } // Rx.FK_Rx_Patient 

    // Foreign keys 
    public virtual LuLanguage LuLanguage { get; set; } // FK_Patient_luLanguage 
    public virtual Pharmacy Pharmacy { get; set; } // FK_Pharmacy_Patient 

    public Patient() 
    { 
     IsInactive = false; 
     CreatedById = 0; 
     UpdatedById = 0; 
     AuditPatientChanges = new System.Collections.Generic.List<AuditPatientChange>(); 
     PatientAddresses = new System.Collections.Generic.List<PatientAddress>(); 
     PatientCallTrackings = new System.Collections.Generic.List<PatientCallTracking>(); 
     PatientContacts = new System.Collections.Generic.List<PatientContact>(); 
     PatientCreditCards = new System.Collections.Generic.List<PatientCreditCard>(); 
     PatientDiseaseStates = new System.Collections.Generic.List<PatientDiseaseState>(); 
     PatientIcd10 = new System.Collections.Generic.List<PatientIcd10>(); 
     PatientMedicalHistories = new System.Collections.Generic.List<PatientMedicalHistory>(); 
     PatientNoteAndComments = new System.Collections.Generic.List<PatientNoteAndComment>(); 
     PatientPayments = new System.Collections.Generic.List<PatientPayment>(); 
     PatientPlanPolicies = new System.Collections.Generic.List<PatientPlanPolicy>(); 
     PatientReferrals = new System.Collections.Generic.List<PatientReferral>(); 
     PatientShareOfCosts = new System.Collections.Generic.List<PatientShareOfCost>(); 
     Rxes = new System.Collections.Generic.List<Rx>(); 
     InitializePartial(); 
    } 

    partial void InitializePartial(); 
} 

、ここで、この問題をテストするJavaScriptコード、クライアント側である:

function testx1(){ 

var patient; 

$.ajax({ 
    type: 'GET', 
    url: "/api/patient/patient/61143", 
    success: function (result) { 
     patient = result; 
     testx2(patient); 
    }, 
    error: function (xhr, options, error) { 
     debugger; 
     alert(error); 
    } 
}); 
} 

function testx2(patient) { 
    patient.LastFourSsn = 5555; 
    patient.ObjectStateEnum = 2; 
    var x = "adsf"; 
    $.ajax({ 
     type: 'POST', 
     url: "/api/patient/patient", 
     data: patient, 
     dataType: "json", 
     success: function (result) { 
     }, 
     error: function (xhr, options, error) { 
     } 
    }); 
} 

マイWebAPIのコード:

 [Route("patient/{id}")] 
    [HttpGet] 
    public async Task<IHttpActionResult> GetPatientByIdAsync(long id) 
    { 
     try 
     { 
      var patient = await patientService.GetPatientByIdAsync(id); 
      if (patient == null) 
       return NotFound(); 
      return Ok(patient); 
     } 
     catch (Exception ex) 
     { 
      return InternalServerError(); 
     } 
    } 

    [Route("patient")] 
    [HttpPost] 
    public async Task<IHttpActionResult> SavePatient(Patient patient) 
    { 
     try 
     { 
      //if (patient.LanguageId == null && patient.LuLanguage?.Id == 0) 
      // patient.LuLanguage = null; 
      //if (patient.PharmacyId == null && patient.Pharmacy?.Id == 0) 
      // patient.Pharmacy = null; 
      IOperationStatus result = await patientService.UpdateAndSavePatientAsync(patient); 
      if (!result.Success) 
       return InternalServerError(new Exception(result.Message)); 
      else 
       return Ok(); 
     } 
     catch (Exception ex) 
     { 
      return InternalServerError(ex); 
     } 
    } 
} 

ここは私ですJsonシリアライザの設定:

public class BrowserJsonFormatter : JsonMediaTypeFormatter 
{ 
    public BrowserJsonFormatter() 
    { 
     this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 
     this.SerializerSettings.Formatting = Formatting.Indented; 
    } 

    public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) 
    { 
     base.SetDefaultContentHeaders(type, headers, mediaType); 
     headers.ContentType = new MediaTypeHeaderValue("application/json"); 
    } 
} 
+0

実際のwebapiメソッドコードも含めることができますか? –

+0

@Wiktor:WebAPIのメソッドコードを含めるために投稿を編集しました。ありがとう。 –

+0

'SavePatient'を呼び出すと、バインドされたパラメータ' patient'にはすでに間違った値(nullではなく0)がありますか? –

答えて

0

問題を解決するためには、いくつかの変更を加えなければなりませんでした。まず、JSON.stringifyをjsonオブジェクトに対して実行しなければなりませんでした。このオブジェクトは、AJAXポストの "contentType: 'application/json'と特に言及しながら、更新のためにサーバーにポストバックされようとしていました。次に、Entity Framework Reverse POCO Generatorを使用せずに、DbContextを生成するために、ADO.NET Entity Data Model拡張で構築されたVSを使用する必要がありました。これらの両方の変更で、事が始まりました。これら両方のツールで生成されたdbContextコードを詳細に調べると、私のタイムスタンプ(rowversion)列がWebAPIメソッドで正しく受信されなかった理由がわかります。しかし、私は時間のクランチだったので、私は別の日のために調査を延期しなければならなかった。それは今のところうまくいっています。すべてのお手伝いをしてくれてありがとう。

編集:この問題を解決しようとしている2つの苦しい日の後に私が見つけたのは、同じ問題を抱えている人がいます。 「Entity Framework Reverse POCO Generator」が{get;}でrowversionプロパティを作成することが判明しました。 プライベートセット}と正しくそうです。しかし、WebAPIメソッドがPOST要求を受け取ったとき、プロセスはおそらくjsonからEntity Classを生成し、その値でタイムスタンプ列を設定することはできません。そこで、.ttファイルを編集して、timestampカラムにパブリックget/set {get; set;}をさせました。これはすべての私の問題を修正しました。私はまだrowversion(タイムスタンプ)列のプライベートセッターが好きで、何とか値を設定していたでしょう。しかし、時間の逼迫のために、私はこの解決策を解決するだけです。

0

あなたの問題は、オブジェクトのシリアル化方法と関係があります。

これを確認するには、LanguageプロパティとLanguageLuプロパティを手動でPOSTに追加します。

function testx2(patient) { 
patient.LastFourSsn = 5555; 
patient.ObjectStateEnum = 2; 
patient.LuLanguage = null; 
patient.Language = null; 
var x = "adsf"; 
$.ajax({ 
    type: 'POST', 
    url: "/api/patient/patient", 
    data: patient, 
    dataType: "json", 
    success: function (result) { 
    }, 
    error: function (xhr, options, error) { 
    } 
}); 

}

これがOKに動作している場合、我々はそこに患者のオブジェクトのシリアル化の問題であり、あなたはあなたが使用しているJSONシリアライザのためのコードを投稿する必要があることをかなり確信することができます。

そうでない場合は、流暢なAPI構文を詳しく見ていきます。

+0

ありがとう。私は自分の投稿を編集してシリアル化設定を表示しました。あなたの答えについては、patient.LuLanguageは、testx2(患者)のjavascript関数によって受け取られると既にnullです。だから、私は手動でもう一度設定する必要はないと思います。このように動作しても、私はそのようなクライアントメソッドによって100以上のエンティティが使用されているので、そのルートに行きたくありません。また、それらの多くは深くネストされたナビゲーションプロパティを持っています。それらをクライアント上で手動ですべて設定することは、生産性に欠けます。ですから、私はより良いソリューション/アプローチを見つける必要があります。 –

+0

@BabuMannavalappilこれは診断目的のためのものです。 Json(de)シリアライザがデフォルトオブジェクトを初期化するようです。 –

関連する問題