I have an ODataController in an Asp.Net Web Api application that allows OData queries. I'm only allowing reads, not updates. Instead of exposing the data model directly, I've created a set of DTOs. The property names on the DTOs do not necessarily match the properties on the EF model. This causes a problem when I try to use the OData query against the EF model. I've looked at other posts on StackOverflow around this subject but none of them seemed to resolve this issue.
Here is what I have right now:
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);
}
This works until I reference specific fields in a select or filter. As soon as I reference a field in my OData query I get an ODataException like - Could not find a property named 'LastName' on type 'MyDataService.Models.RECORD
. This is because the EF properties have a different naming convention. In this case it should be using "LAST_NAME".
It seems like I need to parse the query and then replace the field references with the correct names. I found the ODataUriParser which seems like it could help with this but it's not as clean as I was hoping.
Can anyone provide me some pointers in resolving this issue? Is there a better approach?
OData query option $expand is used to read multiple entities or entity sets in a single service call instead of two different calls. Prerequisite, entity sets which are used should be associated. To know about Association in OData service click here.
For this tutorial, we'll use Entity Framework (EF) Code First to create the back-end database. Web API OData does not require EF. Use any data-access layer that can translate database entities into models.
A DTO (Data Transfer Object) is an object that defines how data will be sent between applications. It's used only to send and receive data and does not contain in itself any business logic.
The WebApi OData new feature Model Aliasing may resolve your problem. You don't have to have the same names between a Edm Model and a aDTO. for example, there is a property name OrderDto.Total, but in Edm Model it becomes 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();
Please reference the ODataModelAliasingSample in https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With