2013-02-21 135 views
10

我有一個ASP.NET WebAPI項目。我最近爲我的所有數據表創建了EntityFramework實體。但我不想將我的數據層&架構暴露給我的用戶。如何將我的實體映射到ViewModel(自動映射?)提供IQueryable返回類型,以便我的API支持OData?使用EF和WebAPI,我如何返回ViewModel並支持IQueryable/OData?

OData支持查詢組合和類似SQL的參數。我想我需要爲查詢組合部分提供某種雙向翻譯?這是否意味着一個自定義的LINQ提供者?我希望比這更容易。

或者我應該放棄IQueryable/OData?

回答

9

我找到了答案在這裏:Web API Queryable - how to apply AutoMapper?

而不是使用[Queryable]可以使用ODataQueryOptions<T>類型的參數來申請的OData行動,打擊你希望的任何類型或LINQ查詢。這裏有一個很好的例子,它甚至不需要使用AutoMapper:

public virtual IQueryable<PersonDto> Get(ODataQueryOptions<Person> odataQuery){ 
    odataQuery.Validate(new ODataValidationSettings(){ 
     AllowedFunctions = AllowedFunctions.AllMathFunctions 
    }); 
    var people = odataQuery.ApplyTo(uow.Person().GetAll()); 
    return ConvertToDtos(people); 
} 

這裏的the Microsoft page解釋這種用法的細節。 (大約下降一半)

+0

這仍然是可行的Web Api 2? – 2014-02-22 00:24:53

+0

絕對!當然如此。現在只有更多的選擇。 – 2014-02-23 17:14:11

+3

我認爲這種方法不再適用。除非將參數更改爲ODataQueryOptions ,否則該方法不會被調用。如果將該參數更改爲該參數,則該方法確實會被調用,但odataQuery.ApplyTo()會引發異常,並說該查詢適用於PersonDto類型,而不是Person類型。 – sheamus 2014-03-24 07:30:49

1

如果您使用的是Automapper,則可以在其中使用投影。例如:

public class ProductsController : EntitySetController<Product, int> 
    { 
     private DbProductsContext _db = new DbProductsContext(); 

     public override IQueryable<ProductDto> Get() 
     { 
      return _db.Products.Project().To<ProductDto>(); 
     } 
    ... 
+0

它真的與使用AutoMapper無關。這是EntityFramework LINQ提供者(至少使用DbContext,有人說ObjectContext不起作用)支持事實,即可以在投影上查詢結果(Select),並且它會識別並將其轉換爲查詢原始數據源。 – Rich 2013-02-21 19:15:34

+0

LINQ如何允許針對視圖模型的查詢轉換爲原始數據源上的查詢?我不明白這一點。我認爲如果我們必須使用類型轉換器(自定義方法)來映射類,它肯定不會起作用。 – 2013-02-22 18:39:42

+0

我知道IQueryable將允許OData查詢針對翻譯的類執行,但是我沒有看到如何在過濾之前檢索所有可能的'Products'並將它們轉換爲'ProductDto'實例的情況下如何工作。 OData查詢如何轉換爲正確的SQL? – 2013-02-23 00:12:25

5

我能夠使用ViewModel類成功地測試這個。

public class InvoiceViewModel 
{ 
    public int InvoiceID { get; set; } 
    public string InvoiceNumber { get; set; } 
} 

中獲得,從你的實體選擇到您的視圖模型:

public override IQueryable<InvoiceViewModel> Get() 
    { 
     var ctx = new CreditPointEntities(); 
     return ctx.Invoices.Select(i => new InvoiceViewModel 
      { 
       InvoiceID = i.InvoiceID, 
       InvoiceNumber = i.InvoiceNumber 
      }).AsQueryable(); 
    } 

確保在webapiconfig.cs

modelBuilder.EntitySet<InvoiceViewModel>("Invoice"); 

本使用視圖模型在模型構建器線,你可以使用一個網址,如

http://website/odata/Invoice?$filter=InvoiceID eq 1

我通過sql分析器確認過濾器正在傳遞給SQL。

相關問題