首页 > 解决方案 > 使用 LINQ to Entities 查询具有一对多关系的父子实体并根据父记录中的值检索子记录

问题描述

我有一个 Asp.net MVC 应用程序,它有 3 个类;事件、修改、FieldHistory。Events 与 Modifications 有一对多的关系,Modifications 也与 FieldHistory 有一对多的关系。

活动类别:

public class Event
{
    public int EventId { get; set; }
    public string EventName { get; set; }
    public DateTime? EventDate { get; set; }
}

改装类:

public class Modification
{
    public int ModificationId { get; set; }

    public int EventId { get; set; }
    public virtual Event Event { get; set; }

    public string ModificationStatus { get; set; }
}

FieldHistory 类:

public class FieldHistory
{

    public int FieldHistoryId { get; set; }

    public int ModificationId { get; set; }
    public virtual Modification Modification { get; set; }

    public int PropValId { get; set; }

    public int KeyFieldId { get; set; }
    public string FieldName { get; set; }
    public string Instructions { get; set; }
    public string Format { get; set; }
}

在其中一个索引操作中,我将修改的 IEnumerable 返回到视图,并将它们显示为索引页面中的列表项。

    public async Task<ActionResult> Index()
    {
        var modifications = _applicationDbContext.Modifications.Include(m 
=> m.Event)
                                .Include(m => m.ItemType)
                                .Include(m => m.ModificationType)
                                .OrderByDescending(m => m.CurrentUserId);


        return View(await modifications.ToListAsync());
    }

我想扩展此查询,以便现在我还将根据 Modification 实体的 ModificationStatus 字段显示 Modifications 及其子记录之一。例如,如果修改状态为“Creating”或“Created”,则加载 PropValId 为 1 的 FieldHistory,否则如果状态为“Processing”或“Approved”,则加载 PropValId 为 2 的 FieldHistory 作为其子项。所以在一个列表项中,我应该在一个记录中包含所有 3 个实体:Event、Modification、FieldHistory

我只是 Linq 的初学者,希望这对我来说是又一大步。

标签: c#entity-frameworklinq

解决方案


不确定是否有直接的方法将 ModificationStatus 与 PropValId 联系起来,因此只需使用您在上面传达的内容,显然如果有更多规则,您必须提供额外的规则......也只会采用一个其他对象类型,但如果您需要所有关联的对象类型,您可以更改它...

我从上面定义的变量修改中提取,当然假设 DbContext 中包含其他对象的表的名称:

    var trios = modifications.Select(m => new { Modification = m, // select the modification obj itself
       FieldHistory = _applicationDbContext.FieldHistories.FirstOrDefault(fh =>
           fh.ModificationId == m.ModificationId && // I am assuming this is required
           fh.PropValId == (new List<string> {"Creating", "Created"}.Contains(m.ModificationStatus) ? 1 : 2)),
       Event = _applicationDbContext.Events.FirstOrDefault(e => e.EventId == m.EventId)
    }).ToList();

这将返回您要查找的内容。如果你愿意,你可以创建一个类,例如:

public class Trio {

    public Modification Modification { get; set; }
    public FieldHistory FieldHistory { get; set; }
    public Event Event { get; set; }

    public Trio (Modification modification, FieldHistory fieldHistory, Event @event)
    {
        this.Modification = modification; 
        this.FieldHistory = fieldHistory;
        this.Event = @event;
    }
}

然后改为:

    var trios = modifications.Select(m => new Trio(m, // select the modification obj itself
       _applicationDbContext.FieldHistories.FirstOrDefault(fh =>
           fh.ModificationId == m.ModificationId && // I am assuming this is required
           fh.PropValId == (new List<string> {"Creating", "Created"}.Contains(m.ModificationStatus) ? 1 : 2)),
       _applicationDbContext.Events.FirstOrDefault(e => e.EventId == m.EventId)
    )).ToList();

推荐阅读