Reputation: 1623
I have the following two models, PatientRegistry
and PartnerRegistry
. The relationship between those models is one to many.
I am trying to read the record and its related one but I am getting a broken JSON at PartnerRegistry
. The only way I got it to work is by using Automapper, but why is this happening? Do I need to call the context for the second model? My understanding is that EF will automatically do that once a relationship is established.
EDIT
I removed some prop just to shorten the list
[Table("PatientsRegistry")]
public class PatientRegistry
{ [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name = "Record Id")]
public long RecordId { get; set; }
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Patient File Number")]
public long PatientFileId { get; set; }
[Required, StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required, StringLength(50)]
public string SecondName { get; set; }
[Required, StringLength(50)]
public string LastName { get; set; }
public int GenderId { get; set; }
public Gender Gender { get; set; }
public DateTime DateCreated { get; set; } = DateTime.UtcNow;
[Timestamp]
public byte[] RowVersion { get; set; }
public ICollection<PartnerRegistry> Partners { get; set; }
public PatientRegistry()
{
Partners = new Collection<PartnerRegistry>();
}
}
public class PartnerRegistry
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long RecordId { get; set; }
public long PatientFileId { get; set; }
public long PartnerFileId { get; set; }
public PatientRegistry PatientsRegistry { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
and my controller is
[HttpGet("{id}")]
public async Task<IActionResult> getAll(long Ids)
{
var patient = await context.PatientsRegistry
.Include(pt => pt.Gender)
.Include(pt => pt.Partners)
.SingleOrDefaultAsync(pt => pt.PatientFileId == Ids);
return Ok(patient);
}
The output is
{
"recordId": 1,
"patientFileId": 1111,
"firstName": "John",
"secondName": "M",
"lastName": "Doe",
"genderId": 1,
"gender": {
"id": 1,
"name": "Male"
},
"dateCreated": "2017-11-25T08:40:07.75444",
"rowVersion": "AAAAAAAAB9E=",
"partners": [{
"recordId": 1,
"patientFileId": 1111,
"partnerFileId": 2222
You can notice that there are missing properties that were not mapped by ef!
The properties that were not populated are, StartDate
and EndDate
Upvotes: 2
Views: 109
Reputation: 1623
also I found that this problem can be resolved globally via this configuration,
services.AddMvc()
.AddJsonOptions(options =>
options.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore);
Upvotes: 1
Reputation: 273701
A quick fix:
public class PartnerRegistry
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long RecordId { get; set; }
public long PatientFileId { get; set; }
public long PartnerFileId { get; set; }
[JsonIgnore] // add this
public PatientRegistry PatientsRegistry { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
Edit, a small mcve:
class Patient
{
public string Name { get; set; }
public ICollection<Partner> Partners { get; set; }
}
class Partner
{
public string Name { get; set; }
//[JsonIgnore]
public Patient Patient { get; set; }
}
with thes classes and Partners filled,
string text = JsonConvert.SerializeObject(patient1);
will throw
Newtonsoft.Json.JsonSerializationException: 'Self referencing loop detected for property 'Patient' with type 'App1.Patient'. Path 'Partners[0]'.'
Upvotes: 1
Reputation: 345
Put [ScriptIgnore]
attribute on the PatientRegistry
Property of the PartnerRegistry
class. This attribute is available from System.Web.Script.Serialization
. There could be a circular references halting the serialization/deserialization.
Upvotes: 1