2015-06-17 59 views
3

對於我們正在使用EF和網頁API 2.抽象來自我們正在使用DTO的我們的數據庫模型遠的一個項目。我們有一個工廠構建這些DTO的:網頁API 2 + EF6 - 構建DTO

public class FooFactory:IModelConverter<FooDTO, Foo> 
{ 

    public FooDTO Create(Foo data) 
    { 
     return new FooDTO() 
     { 
      //Some fields 
     }; 
    } 
} 

在我們的API調用,我們可以這樣做:

public async Task<IHttpActionResult> GetFoo() 
    { 
     var foos = db.Foos 

     //DO STUFF 

     var dtos = (await foos.ToListAsync()).Select(m => _converter.Create(m)); //Converter is an instance of FooFactory) 

     return Ok(dtos); 
    } 

這個工作,但意味着,當我們執行查詢,我們不得不遍歷所有我們的結果並將每個模型轉換爲DTO。

在另一方面,我們可以這樣做:

public async Task<IHttpActionResult> GetFoo() 
    { 
     var foos = db.Foos 

     //DO STUFF 

     return Ok(await foos.Select(m => new FooDTO() { 
      //Assign fields 
     }).ToListAsync()); 
    } 

這將整合這一預測成EF執行查詢。但是這暴露了FooDTO的所有內部細節,我們必須重複所有這些創建代碼。

有沒有辦法做這樣的事情:

public async Task<IHttpActionResult> GetFoo() 
    { 
     var foos = db.Foos 

     //DO STUFF 

     return Ok(await foos.Select(m => _converter.Create(m)).ToListAsync()); 
    } 

這是不行的,因爲LINQ到實體不能與創建函數處理。

我也開放給其他方法與DTO的工作,有沒有更好的方式來做到這一點,或者是有沒有辦法避免通過所有查詢結果額外的傳球?

呵呵,趕上了,我想這樣做沒有 automapper。

+0

您可以隨時創建匿名對象,並返回 – qamar

+0

你不想做的DTO構造函數中的映射? – tmg

回答

5

首先,它似乎更像是一個代碼審查問題。 我建議你不要在你的控制器中直接使用實體框架(你的代碼中的db)。控制器應該很薄,查詢邏輯可能非常複雜。在很多情況下,您需要從數據庫中查詢無法映射到實體的數據。因此,你可以創建存儲庫類,直接返回DTO的:

class FooRepository 
{ 
    public async Task<List<FooDTO>> FindAsync() 
    { 
     using(var context = new DbContext()) 
     { 
      return await context.Foos 
       .Select(m => new FooDTO 
       { 
        Id = m.Id, 
        ... 
       }) 
       .ToListAsync(); 
     } 
    } 
} 

這種方法的另一個好處是,你只查詢你真正需要的數據,現在整個實體。

注:等待是必要的 - 不能直接回到這裏工作。

+0

剛擡起頭:如果你選擇第一個,你沒有ToListAsync, – KWyckmans

+1

錯了,你可以加上「使用System.Data.Entity的」使擴展方法的工作。 – ranquild