如何使用EF组合来自两个相关模型的相关数据?

时间:2017-09-05 07:02:43

标签: c# json entity-framework

概念

我有两个在一对多关系中相关的模型。第一个模型基本上存储患者信息(PatReg)。第二个模型加入合作伙伴(PatPar)。 即(FileId = 1 Sam,FileId = 2 Victoria,FileId = 3 jessica,FileId = 4 monica)信息全部存储在PatReg中。为了说Sam是维多利亚和杰西卡的合作伙伴,我以下列方式加入PatPar

  FileId= 1 FileId=2
  FileId= 1 FileId=3

以下陈述这两个模型。

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; }
    }

获取相关数据 我在项目中使用了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);
    }

结果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,
        }]
    }
}

我希望JSON列表的patPar输出对于每条记录看起来如下所示,

"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,
            }]

问题,fullname存在于主模型PatReg中,但可以通过链接记录而不是fileIdfileIdfileIdparFileId来读取。

换句话说,即使模型中不存在,如何在fullname中添加PatPar值以及其他值?我需要property吗?

更新澄清

我基本上做了三个选择

首先,我使用PatRegId选择记录 第二个PatPar包含相关数据,并使用相同的Id

进行选择

我的问题是fullname,我需要将其包含在PatPar中,但使用不同的密钥选择

第三次选择应该在parFileId中的PatPar FileIDPatReg <{1}}

等效的SQL是

首选:

SELECT FileId, FName, LName, Dob FROM PatReg Where FileId=id 

第二和第三选择:

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

更新

所需的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,
            }]
    }
}

3 个答案:

答案 0 :(得分:4)

使用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;}
}

然后在您的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();

您可以使用AutoMapper

等库来代替手动设置属性

答案 1 :(得分:1)

我的分析是当我们使用相关表时从虚拟属性中创建一个匿名类型:

getInstance()

答案 2 :(得分:0)

感谢Ege Tuncoz

我添加了<div><input name = "name" /></div> <div><input name = "rating" /></div> <div><input name = "name" /></div> <div><input name = "rating" /></div> <div><input name = "name" /></div> <div><input name = "rating" /></div> ... ...

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;}
}