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

如何使用Microsoft.AspNetCore.OData v8.2暴露无键SQL Server视图?

暴露EF无键视图到OData的实现方案

1. 配置EF无键视图模型

首先定义对应数据库视图的实体类,并用EF标记为无键实体:

// 对应SQL Server视图的实体类
public class SalesSummaryView
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public decimal TotalSales { get; set; }
    public DateTime SaleMonth { get; set; }
}

然后在DbContext的OnModelCreating方法中配置无键映射:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<SalesSummaryView>(entity =>
    {
        entity.HasNoKey(); // 明确标记为无键实体
        entity.ToView("SalesSummary"); // 关联到数据库中的视图名
        // 可选:配置列名映射(如果实体属性名和视图列名不一致)
        entity.Property(e => e.ProductId).HasColumnName("ProductID");
        entity.Property(e => e.TotalSales).HasColumnType("decimal(18, 2)");
    });
}

也可以直接在实体类上添加[Keyless]特性替代Fluent API的HasNoKey()。

2. 构建OData模型

在Program.cs(或Startup.cs)中配置OData服务时,注册无键实体并创建对应的EntitySet:

builder.Services.AddControllers().AddOData(options =>
{
    // 启用OData常用查询选项
    options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(null);
    options.AddRouteComponents("odata", GetEdmModel());
});

// 构建EDM模型
private static IEdmModel GetEdmModel()
{
    ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    
    // 注册无键实体类型,并标记为无键
    var salesSummaryEntity = builder.EntityType<SalesSummaryView>().HasNoKey();
    // 添加EntitySet用于暴露该视图的查询接口
    builder.EntitySet<SalesSummaryView>("SalesSummaries");

    return builder.GetEdmModel();
}

注意:无键实体的EntitySet仅支持查询操作,不支持创建、更新、删除。

3. 实现OData控制器

创建继承自ODataController的控制器,实现查询方法并启用OData查询支持:

public class SalesSummariesController : ODataController
{
    private readonly AppDbContext _dbContext;

    public SalesSummariesController(AppDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    [EnableQuery] // 允许使用OData查询参数(如$filter、$orderBy)
    public IActionResult Get()
    {
        // 无键实体默认不被EF跟踪,显式调用AsNoTracking更清晰
        return Ok(_dbContext.SalesSummaryViews.AsNoTracking());
    }
}

可选:实现带参数的OData查询

如果需要带参数的查询(比如按月份筛选),可以通过OData Function实现:

  1. 在EDM模型中注册Function:
private static IEdmModel GetEdmModel()
{
    ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    
    var salesSummaryEntity = builder.EntityType<SalesSummaryView>().HasNoKey();
    builder.EntitySet<SalesSummaryView>("SalesSummaries");

    // 定义按月份查询的Function
    var getSalesByMonthFunc = builder.Function("GetSalesByMonth")
        .ReturnsCollection<SalesSummaryView>()
        .Parameter<DateTime>("month");
    
    // 关联到SalesSummaries实体集
    builder.EntitySet<SalesSummaryView>("SalesSummaries").Function(getSalesByMonthFunc);

    return builder.GetEdmModel();
}
  1. 在控制器中实现对应的方法:
[HttpGet]
[ODataRoute("GetSalesByMonth(month={month})")]
[EnableQuery]
public IActionResult GetSalesByMonth([FromODataUri] DateTime month)
{
    var startDate = new DateTime(month.Year, month.Month, 1);
    var endDate = startDate.AddMonths(1).AddDays(-1);

    var result = _dbContext.SalesSummaryViews
        .Where(s => s.SaleMonth >= startDate && s.SaleMonth <= endDate)
        .AsNoTracking();

    return Ok(result);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 11:27:32