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

EF Core 6/OData管理无键表/实体及GetEdmModel报错解决方案

OData配置无键数据表抛出EDM验证错误的解决方法

问题场景

需要将无键数据类型存储到数据表中,并通过API控制器进行管理,调用GetEdmModel方法时抛出OData验证错误,错误截图如下:
OData验证错误

初始实现代码

实体类定义:

[Keyless]
public class UserDocuments
{
    [StringLength(30)]
    public string UserID { get; set; } = string.Empty;
    public Guid DocumentID { get; set; } = Guid.Empty;
    public int Version { get; set; } = -1;  
}

EDM模型构建逻辑:

public static IEdmModel GetEdmModel()
{    
    ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<UserDocuments>("UserDocuments");
    return builder.GetEdmModel();
}

尝试过的Fluent API配置(未生效):

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<UserDocuments>()
        .HasNoKey()
        .ToTable("UserDocuments");
    base.OnModelCreating(modelBuilder);
}

EF Core中[Keyless]特性与HasNoKey()Fluent配置效果完全等效,但两种方式都无法通过OData的模型验证。

错误原因

OData的EntitySet<T>注册方法仅支持带主键的实体类型,无键类型不符合OData实体集的主键约束要求,直接注册必然抛出验证错误。

可行解决方案

方案1(推荐):配置组合主键替代无键配置

UserDocuments实体中UserID+DocumentID+Version三个字段本身可以唯一标识表中的单行记录,完全不需要配置为无键类型,直接配置组合主键即可同时满足EF Core和OData的规则:

  1. 移除实体类上的[Keyless]特性,删除OnModelCreating中的HasNoKey()配置
  2. 添加组合主键配置:
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserDocuments>()
            .HasKey(ud => new { ud.UserID, ud.DocumentID, ud.Version })
            .ToTable("UserDocuments");
        base.OnModelCreating(modelBuilder);
    }
    
  3. 原有GetEdmModel中的EntitySet<UserDocuments>配置无需修改,启动后不会再抛出验证错误,可正常通过OData控制器管理该表数据。

方案2:保留无键配置,通过OData函数返回集合

如果必须保留EF Core层面的无键配置(例如实体映射的是只读数据库视图),则不能将其注册为实体集,需要注册为复杂类型,通过自定义OData函数返回结果:

  1. 调整EDM模型配置:
    public static IEdmModel GetEdmModel()
    {    
        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
        // 将无键类型注册为复杂类型
        builder.ComplexType<UserDocuments>();
        // 配置返回该类型集合的OData函数
        var getDocsFunc = builder.Function("ListUserDocuments");
        getDocsFunc.ReturnsCollection<UserDocuments>();
        return builder.GetEdmModel();
    }
    
  2. 在控制器中实现对应函数的端点,返回无键实体的查询结果即可。注意该方式不会生成OData默认的实体集路由,仅能通过配置的函数端点访问数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:42:19