Mau*_*odi 4 rest odata asp.net-core-3.1 ef-core-3.1
我正在使用https://www.nuget.org/packages/Microsoft.AspNetCore.OData/7.3.0使用 ASP.NET Core 3.1 API 公开基于 OData 4 的 Querable API
我有带有无键实体(数据库视图)的 EF 数据上下文,当我尝试使用基于 OData 约定的模型公开它时
modelBuilder
.Entity<Student>(eb =>
{
eb.HasNoKey();
eb.ToView("vw_students", "public");
});
Run Code Online (Sandbox Code Playgroud)
这是我的 OData EDM 模型与 EF Core 实体类型的映射
var edmBuilder = new ODataConventionModelBuilder();
edmBuilder.EntitySet<Student>("Students");
return edmBuilder.GetEdmModel();
Run Code Online (Sandbox Code Playgroud)
我在这条线上收到错误 edmBuilder.GetEdmModel() 实体集“Students”基于没有定义键的类型“ODataCore31.Student”。
我的问题 - 1) OData 模型本身支持无键实体类型吗?2)有什么解决方法吗?
要通过 OData 公开无键视图或自定义查询,您必须使用未绑定函数而不是完整的 OData 控制器,后者是通过EntitySet<T>()传统构建器中的表达式进行配置的。
这是有道理的,因为 EntitySet控制器允许基于项目的操作,但如果没有特定的键,则没有传统方法可以将特定项目作为其自己的资源进行寻址。
因此,无键类型是 a
ComplexType而不是Entity,根据定义,实体 必须具有键,以便 OData 可以支持基于项目或键的导航。
将无键集合公开为未绑定函数的OData 方法涉及 3 个重要步骤:
IQueryable<T>未绑定函数或操作的一个具体怪癖是它们没有专门绑定到任何控制器,因此您可以在您选择的任何控制器中声明未绑定端点。
我更喜欢创建一个特定的控制器来托管所有未绑定的组件,名称并不重要,只要它不与域中的其他控制器或实体类型冲突即可。
与默认集合端点一样,我们需要确保我们的端点返回一个IQueryable<Student>,如果您需要该抽象级别,您仍然可以使用IActionResult响应类型,但实现应该是可查询的。
ODataAttributeRouting。这是一个至关重要的元素,在通常的基于约定的实现中,我们不会在每个方法上声明特定的路由,每个控制器的路由前缀是从控制器名称解析的,并且端点是从方法名称解析的。
它有助于尽可能遵循约定,以保持您的实现透明和可配置,如果您始终声明特定路由,那么您配置的路由与
ODataConventionModelBuilder.
在未绑定端点的特定情况下,路由中根本没有控制器元素,这有两个含义:您不能使用在控制器级别指定的路由前缀,因为将前缀留空ODataRouteComponent将触发默认逻辑,这将触发默认逻辑。使用控制器类的名称;并且您必须将端点本身上的路由声明为完整路由,因为所有基于约定的路由都依赖于路由中的控制器元素来映射到控制器以解析可能的端点,因此运行时将不知道要检查哪个控制器。
您可以编写自己的路由解析逻辑,但这超出了此问题的范围。
这是一个最小的控制器实现示例:
注意:在此示例中, routePrefix"odata"是否已注册到 OData 服务
[ODataAttributeRouting]
public partial class ViewsController : ODataController
{
protected AppDbContext _db;
public ViewsController(AppDbContext context)
{
_db = context;
}
[HttpGet("odata/" + nameof(Students))]
[EnableQuery]
public IQueryable<Student> Students(ODataQueryOptions<Student> _queryOptions)
{
return this._db.Students;
}
}
Run Code Online (Sandbox Code Playgroud)
ODataConventionModelBuilder此步骤经常被忽视,如果跳过此步骤,可以通过 HTTP 查询端点,但这是标准的Web API实现,而不是传统的 OData 实现,因此端点不会记录在 CSDL ( $metadata ) 或一些swagger中实现,因此将不可用于 OData 客户端生成器。
var edmBuilder = new ODataConventionModelBuilder();
edmBuilder.Function("Students").ReturnsCollection<Student>();
return edmBuilder.GetEdmModel();
Run Code Online (Sandbox Code Playgroud)
内联服务注册看起来像这样,注意"odata"在AddRouteComponents,它必须与自定义路由声明前缀匹配。
services.AddControllers().AddOData(opt =>
{
var edmBuilder = new ODataConventionModelBuilder();
edmBuilder.Function("Students").ReturnsCollection<Student>();
opt.AddRouteComponents("odata", edmBuilder.GetEdmModel()).EnableQueryFeatures();
}
Run Code Online (Sandbox Code Playgroud)
该解决方案使用 OData 8.0(适用于 .Net 5.0)进行测试和编写,这些概念与 OP 的要求完全兼容ASP.NET Core 3.1和 OData Lib v7.3 完全兼容,但某些命名空间不同。7.3 可以轻松升级到 8 或 9,我鼓励您这样做,因为最新版本中有显着的性能和功能改进。
| 归档时间: |
|
| 查看次数: |
1269 次 |
| 最近记录: |