Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I map an OData query against a DTO to an EF entity?

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?

like image 915
BenR Avatar asked Apr 09 '14 17:04

BenR


People also ask

How do you use $expand in OData?

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.

Does OData require Entity Framework?

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.

What is. net DTO?

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.


1 Answers

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/

like image 185
Tan Jinfu Avatar answered Oct 09 '22 08:10

Tan Jinfu