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

ASP.NET Core OData 8.0 子级集合端点/Documents(1)/Lines(1)/SubLines实现问题

问题修复方案

1. 实体类修正

访问修饰符问题

Document类中的Lines属性无public修饰符,OData无法识别该导航属性,需改为public;同时确保所有导航属性均可访问。

复合主键定义

DocLines的主键应为DocEntry + LineNum(复合键),单个LineNum无法唯一标识记录;DocSubLines同理需设置复合主键(DocEntry + BaseLineId + LineNum)保证唯一性。

修正后的实体类代码:

public class Document
{
    [Key]
    public int DocEntry { get; set; }
    public int DocNum { get; set; }

    // 改为public,OData才能识别导航属性
    public List<DocLines> Lines { get; set; } = new List<DocLines>();
}

public class DocLines
{
    // 复合主键:DocEntry + LineNum
    [Key]
    public int DocEntry { get; set; }
    [Key]
    public int LineNum { get; set; }
    public string ItemCode { get; set; }

    public List<DocSubLines> SubLines { get; set; } = new List<DocSubLines>();
}

public class DocSubLines
{
    // 复合主键:DocEntry + BaseLineId + LineNum
    [Key]
    public int DocEntry { get; set; }
    [Key]
    public int BaseLineId { get; set; }
    [Key]
    public int LineNum { get; set; }
    public string Field { get; set; }
}

2. EDM模型配置修正

需正确配置实体的复合主键及导航关系的可展开性:

public override void BuildGeneratedEdmModel(ODataConventionModelBuilder builder)
{
    var testDocument = builder.EntityType<Document>();
    testDocument.HasKey(c => c.DocEntry);
    testDocument.HasMany(p => p.Lines).IsExpandable();
    
    var testDocumentLine = builder.EntityType<DocLines>();
    // 配置DocLines的复合主键
    testDocumentLine.HasKey(c => new { c.DocEntry, c.LineNum });
    testDocumentLine.HasMany(p => p.SubLines).IsExpandable();

    var testDocSubLines = builder.EntityType<DocSubLines>();
    // 配置DocSubLines的复合主键
    testDocSubLines.HasKey(c => new { c.DocEntry, c.BaseLineId, c.LineNum });

    var testDocuments = builder.EntitySet<Document>("Documents");
}

3. 控制器方法修正

参数不匹配问题

GetSubLinesFromDocument仅接收一个key参数,但/Documents(1)/Lines(1)/SubLines需要两个标识:文档的DocEntry(1)和行的LineNum(1),需添加第二个参数。

方法命名与路由

遵循OData约定修改方法名,或显式添加[ODataRoute]特性指定路由模板。

修正后的控制器代码:

public class DocumentsController : ODataController
{
    private readonly YourDbContext _context;

    // 注入DbContext
    public DocumentsController(YourDbContext context)
    {
        _context = context;
    }

    // odata/Documents working 
    [EnableQuery]
    public IQueryable<Document> Get()
    {
        return _context.Documents.AsQueryable();
    }

    // odata/Documents(1)/Lines working
    [EnableQuery]
    public IQueryable<DocLines> GetLinesFromDocument(int key)
    {
        return _context.DocLines.Where(l => l.DocEntry == key);
    }

    [EnableQuery]
    // 修正路由与参数:匹配/Documents({key})/Lines({lineKey})/SubLines
    [ODataRoute("Documents({key})/Lines({lineKey})/SubLines")]
    public IQueryable<DocSubLines> GetSubLinesFromDocLines(int key, int lineKey)
    {
        // 查询对应文档下指定行的子行
        return _context.DocSubLines.Where(s => s.DocEntry == key && s.BaseLineId == lineKey);
    }
}

额外验证

  1. 确保DbContext中正确配置DbSet<DocLines>和DbSet<DocSubLines>
  2. 启动项目后访问/odata/$metadata,检查EDM模型是否正确生成导航关系和主键定义

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:24:57