2014-04-09 88 views
7

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

这是我现在所拥有的:

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似乎可以帮助这个,但它不像我希望的那样干净。

任何人都可以提供一些解决此问题的指针吗?有更好的方法吗?

回答

5

WebApi OData新功能模型别名可能会解决您的问题。您不必在Edm Model和aDTO之间使用相同的名称。例如,有一个属性名OrderDto.Total,但在EDM模型变得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(); 

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

+0

感谢。这非常有帮助。这只在预发布版本中可用,但看起来很有希望。此外,您可以在模型上使用DataContract和DataMember属性来定义别名。 – BenR

+2

此外,我认为ModelAliasingEnabled属性已被最新版本弃用,但别名仍然有效。 – BenR

+0

在ApiController中实现OData查询时,是否也可以使用此别名? –