【问题标题】:How do I map an OData query against a DTO to an EF entity?如何将针对 DTO 的 OData 查询映射到 EF 实体?
【发布时间】:2014-05-23 01:10:55
【问题描述】:

我在允许 OData 查询的 Asp.Net Web Api 应用程序中有一个 ODataController。我只允许读取,不允许更新。我没有直接公开数据模型,而是创建了一组 DTO。 DTO 上的属性名称不一定与 EF 模型上的属性匹配。当我尝试对 EF 模型使用 OData 查询时,这会导致问题。我查看了 StackOverflow 上围绕这个主题的其他帖子,但似乎都没有解决这个问题。

这是我现在拥有的:

public IQueryable<Customer> GetCustomer(ODataQueryOptions<Customer> query)
{
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Customer>("Customers");
        builder.EntitySet<RECORD>("Records");
        builder.Namespace = "MyDataService.Models";

        var opts = new ODataQueryOptions<RECORD>(new ODataQueryContext(builder.GetEdmModel(), typeof(RECORD)), this.ActionContext.Request);
        var records = (IQueryable<RECORD>)opts.ApplyTo(db.RECORDS);
        return ConvertToCustomerList(records);
}

在我引用选择或过滤器中的特定字段之前,此方法有效。一旦我在 OData 查询中引用了一个字段,我就会得到一个 ODataException,例如 - Could not find a property named 'LastName' on type 'MyDataService.Models.RECORD。这是因为 EF 属性具有不同的命名约定。在这种情况下,它应该使用“LAST_NAME”。

看来我需要解析查询,然后用正确的名称替换字段引用。我发现 ODataUriParser 似乎可以对此有所帮助,但它并不像我希望的那样干净。

谁能给我一些解决这个问题的建议?有更好的方法吗?

【问题讨论】:

    标签: entity-framework asp.net-web-api odata


    【解决方案1】:

    WebApi OData 新功能模型别名可能会解决您的问题。您不必在 Edm 模型和 aDTO 之间使用相同的名称。比如有一个属性名OrderDto.Total,但是在Edm Model中变成了Order.Check

            ODataModelBuilder builder = new ODataConventionModelBuilder();
            builder.ModelAliasingEnabled = true;
    
            EntitySetConfiguration<CustomerDto> customers = builder.EntitySet<CustomerDto>("Customers");
            EntitySetConfiguration<OrderDto> orders = builder.EntitySet<OrderDto>("Orders");
            orders.EntityType.Name = "Order";
            orders.EntityType.Property(p => p.Total).Name = "Check";
            return builder.GetEdmModel();
    

    请参考https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/中的ODataModelAliasingSample

    【讨论】:

    • 谢谢。这非常有帮助。这目前仅在预发布版本中可用,但看起来很有希望。此外,您可以使用模型上的 DataContract 和 DataMember 属性来定义别名。
    • 另外,我认为 ModelAliasingEnabled 属性已被最新版本弃用,但别名仍然有效。
    • 在 ApiController 中实现 OData 查询时是否也可以使用此别名?
    • 我希望在我的控制器中通过 OData 公开 CustomerCustomerDto,在查询 GetAll 时,我希望返回 DTO,而在查询单个对象时, Customer 一个。
    • 这条线是做什么的? orders.EntityType.Name = "订单";您已经在上面设置了 EntitySetConfiguration orders = builder.EntitySet("Orders"); ?只是好奇,谢谢
    猜你喜欢
    • 2014-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多