2014-04-09 2 views
7

Ich habe einen ODataController in einer Asp.Net Web API-Anwendung, die OData-Abfragen ermöglicht. Ich erlaube nur Lesevorgänge, keine Updates. Anstatt das Datenmodell direkt verfügbar zu machen, habe ich eine Reihe von DTOs erstellt. Die Eigenschaftsnamen auf den DTOs stimmen nicht unbedingt mit den Eigenschaften im EF-Modell überein. Das verursacht ein Problem, wenn ich versuche, die OData-Abfrage gegen das EF-Modell zu verwenden. Ich habe andere Beiträge zu diesem Thema in StackOverflow angeschaut, aber keine von ihnen schien dieses Problem zu lösen.Wie ordne ich eine OData-Abfrage für ein DTO einer EF-Entität zu?

Hier ist, was ich jetzt haben:

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); 
} 

Das funktioniert, bis ich bestimmte Felder in einem ausgewählten oder Filter verweisen. Sobald ich ein Feld in meiner OData-Abfrage referenziere, bekomme ich eine ODataException wie - Could not find a property named 'LastName' on type 'MyDataService.Models.RECORD. Dies liegt daran, dass die EF-Eigenschaften eine andere Namenskonvention haben. In diesem Fall sollte "LAST_NAME" verwendet werden.

Es scheint, als müsste ich die Abfrage analysieren und dann die Feldreferenzen durch die richtigen Namen ersetzen. Ich habe den ODataUriParser gefunden, der so aussieht, als könnte er dabei helfen, aber er ist nicht so sauber wie ich gehofft hatte.

Kann mir jemand einige Hinweise zur Lösung dieses Problems geben? Gibt es einen besseren Ansatz?

Antwort

5

Die neue WebAPI OData-Funktion Model Aliasing löst möglicherweise Ihr Problem. Sie müssen nicht die gleichen Namen zwischen einem Edm-Modell und einem aDTO haben. zum Beispiel gibt es einen Eigenschaftsnamen OrderDto.Total, aber in Edm Modell wird es 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(); 

Bitte beachten sie die ODataModelAliasingSample in https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/

+0

Dank. Das war sehr hilfreich. Dies ist nur in der Vorabversion verfügbar, aber es sieht vielversprechend aus. Außerdem können Sie die Attribute DataContract und DataMember für das Modell verwenden, um den Alias ​​zu definieren. – BenR

+2

Außerdem denke ich, dass die ModelAliasingEnabled -Eigenschaft mit der neuesten Version veraltet ist, aber Aliasing immer noch funktioniert. – BenR

+0

Kann dieses Aliasing auch bei der Implementierung von OData-Abfragen in einem ApiController verwendet werden? –