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

如何在ASP.NET Core中使用无主键数据库表(EF Core+OData场景)

处理ASP.NET Core中无主键的数据库表(EF Core + OData场景)

我刚好碰到过类似的棘手场景,EF Core本身要求实体必须有主键才能正常生成和操作,而OData也依赖键来实现路由和查询功能,所以得从EF Core和OData两个层面配合处理:


1. 先解决EF Core的实体映射问题

因为你没有权限修改数据库,所以只能在代码层面做配置,分两种常见情况处理:

情况A:表有唯一组合列(可作为逻辑主键)

如果cmn.ReshteNerkhItem表存在一组列的组合是全局唯一的(比如ReshteId+ItemId),那可以把这组列设为复合主键,这样EF Core就能正常识别实体了:

方法1:用数据注解标注实体

手动创建对应的实体类(因为scaffold工具失败,只能自己写):

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace YourProject.Models.Entities
{
    [Table("ReshteNerkhItem", Schema = "cmn")]
    public class ReshteNerkhItem
    {
        // 用[Key] + [Column(Order)]定义复合主键的顺序
        [Key]
        [Column(Order = 1)]
        public int ReshteId { get; set; }

        [Key]
        [Column(Order = 2)]
        public int ItemId { get; set; }

        // 其他列根据数据库表结构逐一添加
        public decimal NerkhValue { get; set; }
        public DateTime CreatedAt { get; set; }
    }
}

方法2:用Fluent API配置(更灵活,推荐)

在你的SeeMiddleContext的OnModelCreating方法中添加配置:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // 给ReshteNerkhItem配置复合主键
    modelBuilder.Entity<ReshteNerkhItem>()
        .HasKey(r => new { r.ReshteId, r.ItemId });

    // 保留scaffold生成的其他表配置
    base.OnModelCreating(modelBuilder);
}

情况B:表没有任何唯一列(完全无主键)

这种情况EF Core提供了HasNoKey()的特殊配置,允许你映射无主键的表,但要注意:EF Core不支持对这类实体做Update/Delete操作,只能执行查询和插入:

首先创建不带主键注解的实体类:

using System.ComponentModel.DataAnnotations.Schema;

namespace YourProject.Models.Entities
{
    [Table("ReshteNerkhItem", Schema = "cmn")]
    public class ReshteNerkhItem
    {
        // 所有列都不需要加[Key]注解
        public int SomeColumn { get; set; }
        public string AnotherColumn { get; set; }
        public decimal NerkhValue { get; set; }
    }
}

然后在DbContext中配置无主键映射:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<ReshteNerkhItem>()
        .HasNoKey(); // 明确告诉EF Core这个实体没有数据库主键

    base.OnModelCreating(modelBuilder);
}

2. 适配OData的键要求

OData必须为每个实体集定义键才能正常工作,所以即使你用了HasNoKey()的EF配置,也要给OData指定一个“逻辑键”(哪怕是临时选的列):

新建一个OData模型配置类:

using Microsoft.OData.ModelBuilder;

public class ReshteNerkhItemODataConfig : IEdmModelConfiguration
{
    public void Apply(ODataModelBuilder builder)
    {
        var entitySet = builder.EntitySet<ReshteNerkhItem>("ReshteNerkhItem").EntityType;
        // 随便选一个列作为OData的键(比如SomeColumn),只要能让OData识别实体即可
        entitySet.HasKey(r => r.SomeColumn);
    }
}

然后在Program.cs(或Startup.cs)中注册OData时加载这个配置:

builder.Services.AddControllers().AddOData(options =>
{
    options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(100);
    options.AddRouteComponents("odata", GetEdmModel());
});

// 定义Edm模型的辅助方法
private static IEdmModel GetEdmModel()
{
    var builder = new ODataConventionModelBuilder();
    // 应用自定义的ReshteNerkhItem配置
    new ReshteNerkhItemODataConfig().Apply(builder);
    // 添加其他实体集的配置...
    return builder.GetEdmModel();
}

最后补充的注意事项

  • 用复合主键的实体,EF Core和OData都能正常支持所有CRUD操作
  • 用HasNoKey()的实体,只能做查询和插入,执行Update/Delete会直接报错(因为EF无法定位要修改的行)
  • 如果你的OData接口需要完整支持修改操作,最好还是和DBA沟通,看能不能给表加一个自增主键列——这是最彻底的解决方案,不过你说没权限的话,就只能用前面的方法替代了

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:44:15