2010-09-08 90 views
6

關於實體Framework4,Lambda表達式和數據傳輸對象(DTO),我有一個半複雜的問題。EF4,Lambda,存儲庫模式和DTO

因此,我有一個小型的EF4項目,並遵循既定的面向對象原則,我有一個DTO在數據使用者(GUI)和數據模型之間提供一個抽象層。

  • VideoDTO = DTO與getter/setter方法,由EF4
  • 生成的GUI
  • VideoEntity =實體使用

我的問題是圍繞由GUI使用DTO的(和不具有GUI使用實體),結合需要傳遞一個lambda到數據層。我的數據層是Add的基本存儲庫模式。更改,刪除,獲取,的GetList等 試圖執行一個簽名查找方法,像這樣:

public IEnumerable<VideoDTO> Find(Expression<Func<VideoEntity, bool>> exp) 
... 
_dataModel.Videos.Where(exp).ToList<Video>() 
--- 

我的問題/關心的是「EXP」需要爲類型VideoEntity代替VideoDTO的。我想保留關注的分離,以便GUI不知道實體對象。但如果我試圖通過

Func<VideoDTO, bool> 

我不能再做一個LINQ在那個表達式上使用實際的數據模型。

有沒有辦法到Func<VideoDTO,bool>轉換爲Func<VideoEntity, bool>

理想的情況下我的方法簽名會接受Func<VideoDTO, bool>和這樣的GUI就沒有參考的基礎數據實體。

這足夠清楚了嗎?謝謝你的幫助


感謝您的repliesto你們倆。

我會嘗試在對象中定義搜索條件並在LINQ表達式中使用它的想法。剛開始使用EF4和L2S時,將其用作學習項目。

再次感謝!

回答

0

也許您的設計目標是防止數據模型實體傳播到客戶端層,而不是防止表示層和數據模型之間的依賴關係。如果按照這種方式來看,那麼查詢就像你所說的那樣形成就沒有問題。

若要進一步您可以通過接口(IVideoEntityQueryFields)從VideoEntity公開可搜索字段並將其用作表達式中的類型。

如果您不想將接口添加到實體,則更復雜的選項是使用VideoEntityQuery對象,並將Expression<Func<VideoEntityQuery,bool>>轉換爲Expression<Func<VideoEntity,bool>>

1

在像CQRS這樣的體系結構中,根本不需要這樣的轉換,因爲讀取&應用程序的寫入側是分開的。

但在你的情況下,你不能從翻譯失控。

首先 - 定義庫時,你應該更具體。存儲庫簽名是你想保持顯式而不是通用的東西。

常見例子來說明這個想法 - 你可以告訴索引時,你看看你的資料庫簽名您需要在數據庫中(也許看着倉庫實現,但可以肯定的w/o看着客戶端代碼)?你不能。因爲它太泛化,客戶端可以搜索任何東西。

在你的例子這是一個好一點的原因表達這種通用栓與DTO,而不是實體。

這是我做什麼(使用NHibernate.Linq,但這個想法仍然)

public class Application{ 
    public Project Project {get;set;}  
} 

public class ApplicationRepository{ 
public IEnumerable<Application> Search(SearchCriteria inp){ 
     var c=Session.Linq<Application>(); 
     var q=c.AsQueryable(); 
     if(!string.IsNullOrEmpty(inp.Acronym)) 
     q=q.Where(a=>a.Project.Acronym.Contains(inp.Acronym)); 
     /*~20 lines of similar code snipped*/ 
     return q.AsQueryable(); 
} 
} 

//used by client 
public class SearchCriteria{ 
public string Acronym{get;set;} 
/*some more fields that defines how we can search Applications*/ 
} 

如果你想保持你的表情,一個方法是手動定義詞典是這樣的:

後來
var d=new Dictionary<Expression<Func<VideoDTO,object>>, 
        Expression<Func<VideoEntity,object>>{ 
    {x=>x.DtoPropNumberOne,x=>x.EntityPropNumberOne} /*, {2}, {3}, etc.*/ 
}; 

並使用它:

//can You spot it? 
//client does not know explicitly what expressions dictionary contains 
_dataModel.Videos.Where(d[exp]).ToList<Video>(); 
//and I'm not 100% sure checking expression equality would actually work 

如果你不想手動編寫的映射字典,Y你需要一些先進的技術。一個想法是DTO表達字符串,然後轉換回實體表達。 Here有一些想法(整理相關的雖然),這可能有助於。表情是相當複雜的野獸。

反正 - 正如我說的,你應該避免這種情況。否則 - 你會產生非常脆弱的代碼。