You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Entity Framework Core/Razor查询一对多关联数据避免主记录重复方案

解决方案

问题根源

  • 现有LINQ查询使用双from子句实现内连接,每匹配到1个附件就生成1条独立记录,消息主体会随附件数量重复返回
  • 视图模型ViewMessageModel仅设计了单附件字段,无法存储一条消息对应的多个附件数据

步骤1:调整视图模型结构,支持一对多关联存储

修改ViewMessageModel,新增附件集合字段:

public class ViewMessageModel
{
    public int id { get; set; }
    public string subject { get; set; }
    public string message { get; set; }
    public DateTime create_date { get; set; }
    // 存储当前消息关联的所有附件
    public List<DocumentItem> Documents { get; set; } = new();
}

// 附件独立传输类,按需保留需要的字段
public class DocumentItem
{
    public string fileName { get; set; }
    public byte[] content { get; set; }
}

步骤2:修改LINQ查询逻辑,按消息分组关联附件

方案A(推荐):给实体配置导航属性,使用EF Core预加载

先给MessageModel新增导航属性,EF Core会自动根据外键messageId匹配关联关系:

public class MessageModel
{
    public int id { get; set; }
    public string subject { get; set; }
    public string message { get; set; }
    public DateTime created { get; set; }
    // 导航属性:一条消息对应多个附件
    public List<DocumentModel> Documents { get; set; } = new();
}

查询代码直接使用Include预加载关联附件:

var messages = project.MessagesModel
    .Include(m => m.Documents)
    .Select(m => new ViewMessageModel
    {
        id = m.id,
        subject = m.subject,
        message = m.message,
        create_date = m.created,
        Documents = m.Documents.Select(d => new DocumentItem
        {
            fileName = d.fileName,
            content = d.content
        }).ToList()
    })
    .ToList();

方案B:无需修改实体,直接使用GroupJoin分组查询

如果不想修改原有实体结构,直接用分组连接实现一对多查询:

var messages = (from m in project.MessagesModel
                join md in project.messageDocument on m.id equals md.messageId into docGroup
                select new ViewMessageModel
                {
                    id = m.id,
                    subject = m.subject,
                    message = m.message,
                    create_date = m.created,
                    Documents = docGroup.Select(d => new DocumentItem
                    {
                        fileName = d.fileName,
                        content = d.content
                    }).ToList()
                }).ToList();

步骤3:调整视图渲染逻辑,嵌套循环输出附件

修改视图代码,外层循环输出消息主体,内层循环输出该消息的所有附件:

@using project.Models;
@model List<ViewMessageModel>

@foreach (var message in Model)
{
    <div>@message.id</div>
    <div>@message.subject</div>
    <div>@message.message</div>
    <div>@message.create_date</div>
    <div>附件:</div>
    @foreach (var doc in message.Documents)
    {
        <div>@doc.fileName</div>
    }
    <hr />
}

内容的提问来源于stack exchange,提问作者Tumo Maraisane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 03:54:01