[英]How to combine related data from two related models using EF?
Concept 概念
I have two models that are related in one to many relationship. 我有两个相互关联的模型。 the first model basically stores patients information ( PatReg
). 第一个模型基本上存储患者信息( PatReg
)。 the second Model join partners together ( PatPar
). 第二个模型将合作伙伴( PatPar
)联合在一起。 ie (FileId=1 Sam, FileId=2 Victoria, FileId=3 jessica, FileId=4 monica) info are all stored in PatReg
. 即(FileId = 1 Sam,FileId = 2 Victoria,FileId = 3 jessica,FileId = 4 monica)信息都存储在PatReg
。 in order to say that Sam is a partner to Victoria and Jessica I join them in PatPar
the following fashion: 为了说Sam是Victoria和Jessica的合伙人,我以以下方式加入PatPar
:
FileId= 1 FileId=2
FileId= 1 FileId=3
the following states these two models. 下面说明这两个模型。
public class PatReg
{
public Int64 FileId { get; set; }
[Required, Display(Name = "First Name")]
public string FName { get; set; }
[Required, Display(Name = "Middle Name")]
public string MName { get; set; }
[Required, Display(Name = "Last Name")]
public string LName { get; set; }
[Display(Name = "Full Name"), NotMapped]
public string fullname
{
get { return FName + " " + MName + " " + LName; }
}
[Required, Display(Name = "Date of Birth")]
[DataType(DataType.Date)]
public DateTime Dob { get; set; }
public ICollection<PatPar> PatPar { get; set; }
}
public class PatPar
{
[Key]
public Int64 RecId { get; set; }
[Display(Name = "Patient File Id"), Required]
public Int64 FileId { set; get; }
[Display(Name = "Partner File Id"), Required]
public Int64 ParFileId { set; get; }
[Display(Name = "Start Date"), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true), Required]
public DateTime SDate { set; get; }
[Display(Name = "End Date"), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime? EDate { set; get; }
}
Getting Related Data I m using an API controller
in my project, the way I query my record is as follows, 在项目中使用API controller
获取相关数据时 ,查询记录的方式如下:
[HttpGet("{id}")]
public async Task<IActionResult> GetPatReg([FromRoute] long id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var patReg = await _context.PatReg.SingleOrDefaultAsync(m => m.FileId == id); // here I get my Main Record
var patRegPar = await _context.PatPar // here I get related Records
.Where(m => m.FileId == id)
.ToListAsync();
if (patReg == null)
{
return NotFound();
}
var DataRes = new {
sdata = patReg
};
return Ok(DataRes);
}
Resulting JSON
结果JSON
{
"sdata": {
"fileId": 1708010001,
"fName": "Json",
"mName": "S",
"lName": "Makenzi",
"fullname": "Json S Abu Makenzi",
"dob": "1984-04-26T00:00:00",
"patPar": [{
"recId": 2,
"fileId": 1708010001,
"parFileId": 1708010002,
"sDate": "1999-12-12T00:00:00",
"eDate": null,
}, {
"recId": 3,
"fileId": 1708010001,
"parFileId": 1708010003,
"sDate": "1955-12-14T00:00:00",
"eDate": null,
}]
}
}
I want my JSON
output for patPar
list to look like the following for each record, 我希望patPar
列表的JSON
输出看起来像每个记录的以下内容,
"patPar": [{
"recId": 2,
"fullname": "Json S Abu Makenzi",
"fileId": 1708010001,
"parFileId": 1708010002,
"sDate": "1999-12-12T00:00:00",
"eDate": null,
}, {
"recId": 3,
"fullname": "Sarah S Maz",
"fileId": 1708010001,
"parFileId": 1708010003,
"sDate": "1955-12-14T00:00:00",
"eDate": null,
}]
The problem, the value fullname
exists in the Main model PatReg
but can be read via linking records instead of fileId
to fileId
, fileId
to parFileId
. 问题是, fullname
的值存在于Main模型的PatReg
但是可以通过链接记录而不是fileId
到fileId
, fileId
到parFileId
来parFileId
。
in another words, How can I add the fullname
value in PatPar
along with the other values even if it does not exist in the model? 换句话说,即使模型中不存在fullname
值,我如何将其与其他值一起添加到PatPar
中? do I need a property
for it? 我需要property
吗?
Update for clarification 更新以澄清
I m doing basically Three selections 我基本上是在做三个选择
first I select the record from PatReg
using Id
second PatPar
has related data and are getting selected using the same Id
首先,我使用Id
从PatReg
选择记录;第二, PatPar
具有相关数据,并且正在使用相同Id
My issue is the fullname
, I need to include it in PatPar but with a different key selection 我的问题是fullname
,我需要将其包括在PatPar中,但要选择其他键
Third Selection should goes as parFileId
in PatPar
to FileID
in PatReg
第三个选择应该去为parFileId
在PatPar
以FileID
在PatReg
the equivalent SQL is 等效的SQL是
first selection: 首选:
SELECT FileId, FName, LName, Dob FROM PatReg Where FileId=id
Second and third selection: 第二和第三选择:
SELECT PatReg.FileId, PatReg.FName, PatReg.MName, PatReg.LName, PatPar.EDate, PatPar.ParFileId, PatPar.SDate, PatReg_1.FName AS PFName, PatReg_1.MName AS PMName, PatReg_1.LName AS PLName
FROM PatPar INNER JOIN
PatReg ON PatPar.FileId = PatReg.FileId INNER JOIN
PatReg AS PatReg_1 ON PatPar.ParFileId = PatReg_1.FileId
Update 更新资料
Desired JSON is 所需的JSON是
{
"sdata": {
"fileId": 1708010001,
"fName": "**",
"mName": "**",
"lName": "**",
"fullname": "***",
"dob": "1984-04-26T00:00:00",
"patPar": [{
"recId": 2,
"fullname": "*****",
"fileId": 1708010001,
"parFileId": 1708010002,
"sDate": "1999-12-12T00:00:00",
"eDate": null,
}, {
"recId": 3,
"fullname": "*****",
"fileId": 1708010001,
"parFileId": 1708010003,
"sDate": "1955-12-14T00:00:00",
"eDate": null,
}]
}
}
It's a good practice to use DTOs(Data Transfer Objects) to transfer data between two endpoints. 使用DTO(数据传输对象)在两个端点之间传输数据是一个好习惯。 This way you can specify what properties you want to share, edit your model as you wish and you can get rid of those noisy properties that you wont use. 这样,您可以指定要共享的属性,根据需要编辑模型,并摆脱那些您不会使用的嘈杂属性。 In this case you can add a class like below : 在这种情况下,您可以添加如下所示的类:
public class PatParDto
{
public int RecId { get; set; }
public int FileId { get; set; }
public int ParFileId { get; set; }
public DateTime SDate { get; set; }
public DateTime? EDate { get; set; }
public string FullName {get; set;}
}
and then in your linq query you can select your PatPar as PatPatDto : 然后在linq查询中,您可以选择PatPar作为PatPatDto:
var patRegPar = await _context.PatPar
.Where(m => m.FileId == id)
.Select(m => new PatParDto {
//Here you can set properties
FullName = patReg.fullname,
RecId = m.RecId
})
.ToListAsync();
Instead of setting properties manually you can use a library like AutoMapper 您可以使用像AutoMapper这样的库来代替手动设置属性
my seggestion is to make an anonymous type from the virtual property when we use the related table: 我的分类是在使用相关表时从虚拟属性中创建匿名类型:
var patRegPar = await _context.PatPar // here I get related Records
.Include(c=>c.PatReg)
.Where(m => m.FileId == id)
.Select(t=>new{ recId = t.recId , fullname = t.PatReg.fullname , ... })
.ToListAsync();
Thanks Ege Tuncoz 感谢Ege Tuncoz
I added the DTO
, 我添加了DTO
,
public class PatParDto
{
public int RecId { get; set; }
public int FileId { get; set; }
public int ParFileId { get; set; }
public DateTime SDate { get; set; }
public DateTime? EDate { get; set; }
public string FullName {get; set;}
}
then in my controller I ran a loop to add the desired value for each record in the DTO. 然后在我的控制器中运行一个循环,为DTO中的每个记录添加所需的值。
[HttpGet("{id}")]
public async Task<IActionResult> GetPatReg([FromRoute] long id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var patReg = await _context.PatReg
.Where(m => m.FileId == id)
.ToListAsync();
var patpar = await _context.PatPar.Select(m => new PatParDto {
RecId = m.RecId,
FileId = m.FileId,
ParFileId = m.ParFileId,
SDate = m.SDate,
EDate = m.EDate,
}).ToListAsync();
for (int i = 0; i < patpar.Count; i++)
{
patpar[i].FullName = (from a in _context.PatReg
where (a.FileId == patpar[i].ParFileId)
select new { a.fullname }
).Single().fullname;
or
patpar[i].FullName = _context.PatReg.Where(a =>
a.FileId == patpar[i].ParFileId)
.Select(t=>new {t.fullname })
.Single().fullname;
}
if (patReg == null)
{
return NotFound();
}
var DataRes = new {
sdata = patReg,
test= patpar
};
return Ok(DataRes);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.