【问题标题】:.NET ODataController class to return collection of type strutcurally unrelated to type for controller.NET ODataController 类返回与控制器类型结构无关的类型集合
【发布时间】:2016-05-04 14:30:12
【问题描述】:

我有一个类,MyClassController,它继承自 ODataController。我已经能够使用“自动”路由来访问缩放器集合类型的属性,例如,/path/to/MyClass(100)/SomeProperty。我现在需要返回一个在结构上与MyClass 无关的类的集合(即,没有连接这两个类的引用),但从逻辑上讲,两者之间存在关系。我希望能够做类似GETting /path/to/MyClass(100)/RelatedThings/ 的事情。我该如何设置?我正在使用Application_Start 中的ODataConventionModelBuilder.EntitySet<> 设置MyClass 及其相关类。

我正在使用 Microsoft.OData.Core 6.13.0 (OData 4.0)。

编辑:我从这个问题中遗漏了一些我没有意识到与我在应用程序其他地方做出的一些设计决策相关的细节,所以我接受了最好的答案在不考虑这些细节的情况下解决了这个问题。我最终在返回相关内容的 MyClass 控制器中创建了一个绑定的 OData 函数。我发现如果我没有包含命名空间或尾部斜杠,HTTP 请求会产生错误。也就是说,/path/to/MyClass(100)/Default.RelatingThings/ 有效。我正在研究消除对斜杠和命名空间的需求的方法。 (编辑:在设置 OData 路由时调用 config.EnableUnqualifiedNameCall(true);请参阅 https://stackoverflow.com/a/35156885/1102726。)

【问题讨论】:

    标签: c# asp.net odata


    【解决方案1】:

    您的 OData 路由不必与存储架构中的关系匹配;即,缺乏结构关系是无关紧要的。只需向MyClass 添加一个类似于以下内容的属性:

    public ICollection<Thing> RelatedThings { get; set; }
    

    然后为属性定义一个动作方法:

    public IQueryable<Thing> GetRelatedThings([FromODataUri] int key)
    {
        // Fill-in data access logic.
    }
    

    您不会请求/path/to/MyClass(100)?$expand=RelatedThings,但您可以根据需要请求/path/to/MyClass(100)/RelatedThings

    【讨论】:

    • 我确实考虑过这一点,但我想保持域对象的工作方式在相似的域对象之间保持一致。如果我按照您建议的方式更改数据模型,它将是我们模型中唯一一个来自自动水合的普通旧 CLR 对象的引用引用了一个不是的对象的地方。 (我们的一些域对象来自 NHibernate,而另一些来自 JSON HTTP 服务。)我也非常反对有一个带有评论的属性,“永远不要使用这个属性;它就在这里,所以 OData 不会抱怨。 "
    • OData 服务公开的实体和关系不必直接匹配存储架构中的对象和关系。分别对存储对象和 OData 实体进行建模,并使用 AutoMapper 之类的库在这两个模型之间进行转换。这种方法可以让您公开MyClassRelatedThings 之间的逻辑关系,而无需公开对象存储方式或存储位置的任何细节。
    • 不过,我也想要它们。这让我的 ORM 处理分页而不是过滤而不是让 ORM 水合整个结果集。我也不想添加数据的另一种表示形式。领域对象、用于业务逻辑操作的数据传输对象和视图模型就足够了,尤其是当我添加另一种表示的原因是作为真正路由问题的解决方法时。
    【解决方案2】:

    由于您的数据在结构上不相关,您将无法扩展到相关实体。有一个用于数据聚合、连接的 oData 扩展

    使用扩展,它看起来像:

    ~/$crossjoin(Products,Sales)
                         ?$expand=Products($select=Name),Sales($select=Amount)
                         &$filter=Products/ID eq Sales/ProductID
    

    你可以看到Cross Joining in OData的完整示例

    【讨论】:

    • 感谢您的回复。我不熟悉 OData 交叉连接,但考虑到我想做的事情,这似乎太复杂了。我不想得到所有的产品和所有的销售额。我只想获得特定产品的销售额。在你的例子中,我会是GETting /path/to/$crossjoin(Product,Sales)?$filter=Products/ID eq Sales/ProductID and Products/ID = 2358。有没有办法使用/path/to/Product(2358)/?我还可以为 Sales 创建一个新控制器,但我想确保需要产品 ID。顺便说一句,我喜欢你的手柄和头像。
    • 您可以在两个请求中执行此操作,您可以向您的班级发出请求,然后向您的子班级发出另一个请求,其中另一个 id 匹配,然后只需在 javascript 或您的任何地方加入您的结果消耗数据,ps是的,短路是一部很棒的电影
    • 我不确定如何将第一类的 ID 作为第二类的强制参数。我试着做一个函数,最后签出了aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/…。 (我不记得我是怎么发现的,但它非常有用!)无论如何,如果我要使用 IQueryable&lt;RelatedThing&gt; Get() 方法创建 RelatedThingsController,有没有办法为父 ID 添加必需的参数?跨度>
    • 我确实考虑过制作一个 OData 函数来返回 MyClassController 中的 RelatedThing 集合,但我不知道如何摆脱 Default. 命名空间,但这可能也是一种选择。
    • 查看此链接,您也许可以创建一个操作过滤器,之后加入实体stackoverflow.com/questions/29953323/…
    猜你喜欢
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 2019-04-09
    • 2022-01-04
    • 1970-01-01
    相关资源
    最近更新 更多