1

這個問題不讓我睡覺,因爲一年以來,我試圖找到一個解決方案,但是...在我的腦海中仍然沒有發生任何事情。可能你可以幫助我,因爲我認爲這是一個非常普遍的問題。n層應用程序中的實體框架 - 懶惰加載與急切加載模式

我有一個n層應用程序:表示層,業務邏輯層,模型層。假設爲了簡單起見,我的應用程序在表示層中包含允許用戶搜索客戶的表單。現在用戶通過用戶界面填充過濾器並點擊一個按鈕。發生某些事情並且請求到達表示層,如CustomerSearch(CustomerFilter myFilter)。這個業務邏輯層現在保持簡單:在模型上創建一個查詢並獲取結果。

現在的問題是:您如何面對加載數據的問題?我的意思是業務邏輯層不知道那個特定的方法會被這個表單調用。所以我認爲它不知道請求表單是否只需要客戶對象或客戶對象與鏈接的訂單實體。

我試圖更好地解釋: 我們的表單只是想列出按姓氏搜索的客戶。它與訂單無關。因此,業務邏輯查詢將如下所示:

(from c in ctx.CustomerSet 
where c.Name.Contains(strQry) select c).ToList(); 

現在這個工作正常。兩天後,您的老闆會要求您添加一張表單,讓您可以像查找其他客戶一樣搜索客戶,並且需要顯示每位客戶創建的訂單總數。現在我想重複使用該查詢並添加附加的邏輯(包括)訂單並返回。

你會如何面對這一要求?

這是我從現在開始的最好的(我認爲)的想法。我想聽聽您的意見: 在BLL我CustomerSearch方法不直接創建查詢,但通過該構成的ObjectQuery像私有擴展方法:

private ObjectQuery<Customer> SearchCustomers(this ObjectQuery<Customer> qry, CustomerFilter myFilter) 

private ObjectQuery<Customer> IncludeOrders(this ObjectQuery<Customer> qry) 

但這並不能說服我,因爲它看起來太複雜了。

感謝, 馬爾科

回答

1

考慮遷移到DTO的表示層和業務層之間的接口,例如參見: - http://msdn.microsoft.com/en-us/magazine/ee236638.aspx

像Automapper東西可以緩解很多與移動相關的疼痛到DTOs,這一舉動將明確你可以做什麼,不能做什麼查詢的結果,也就是說,如果它在DTO上被加載,如果它不是你需要一個不同的DTO。

您目前的計劃聽起來表現層和數據層之間的耦合過於緊密。

+0

感謝您的非常非常快速的答案。所以你認爲這是一個在演示層而不是業務實體中使用DTO的情況? 謝謝 Marco – Marconline 2010-04-10 00:02:28

+0

聽起來好像您的應用程序正在接近它值得的大小/複雜性點。在轉向DTO時總是有一個權衡,因爲它們總體上增加了複雜性,但像Automapper這樣的工具可以減少它變得有價值的點。 – 2010-04-10 00:36:49

+0

感謝您的建議。我會絕對檢查DTO和Automapper。再次感謝你。 – Marconline 2010-04-10 09:07:51

1

我同意來自Hightechrider關於使用DTO的評論,但是您有關於商業實體的有效問題。

一個可能的解決方案(我正在開發一個項目中沿着這些線使用某些東西)是使用只讀的DTO(至少從表示層的角度來看。你的查詢/獲取操作只會返回DTO,這會給你延遲加載的能力。

您可以將您的業務層設置爲在更新/創建對象/實體時返回包裝DTO的可編輯對象。您的可編輯對象可以強制執行任何業務規則,然後在將其保存/傳遞到業務層時,它所包裝的DTO(使用更新的值)可以傳遞到數據層。

public class Editable 
{ 
    //.......initialize this, other properties/methods.... 

    public bool CanEdit<TRet>(Expression<Func<Dto, TRet>> property) 
    { 
     //do something to determine can edit 
     return true; 
    } 

    public bool Update<TRet>(Expression<Func<Dto, TRet>> property, TRet updatedValue) 
    { 
     if (CanEdit(property)) 
     { 
      //set the value on the property of the DTO (somehow) 
      return true; 
     } 
     return false; 
    } 

    public Dto ValueOf { get; private set;} 
} 

這使您能夠強制用戶是否可以從業務層獲得可編輯對象,以及允許業務對象強制執行,如果用戶有權限編輯對象的特定屬性的能力。我遇到的一個常見問題是,有些用戶可以編輯所有的屬性,其他用戶則不能,而任何人都可以查看屬性的值。此外,表示層可以根據業務層的指示和執行情況確定要公開的內容,以供用戶編輯。

我的其他想法是你的業務層不能暴露IQueryable或將標準表達式作爲傳遞給你的數據層的參數。例如,我有一個頁面構建查詢是這樣的:

public class PageData 
{ 
    public int PageNum; 
    public int TotalNumberPages; 
    public IEnumerable<Dto> DataSet; 
} 

public class BL 
{ 
    public PageData GetPagedData(int pageNum, int itemsPerPage, Expression<Func<Dto, bool>> whereClause) 
    { 
     var dataCt = dataContext.Dtos.Where(whereClause).Count(); 
     var dataSet = dataContext.Dtos.Where(whereClause).Skip(pageNum * itemsPerPage).Take(itemsPerPage); 

     var ret = new PageData 
         { 
          //init this 
         }; 

     return ret; 
    } 
} 
+0

感謝您的建議!幸運的是,我沒有授權問題,但這對其他項目來說是一個很好的解決方案。關於將查詢(作爲表達式)傳遞給BL:我不太喜歡它,但可能這對我來說只是一個樣式問題。我希望表示層儘可能的可讀性和可讀性。即我喜歡看到類似GetCustomersByCountry和GetCustomersByCity的東西,而不是「通用」GetCustomers(查詢),但是 - 再次 - 我認爲這只是一個sylistic問題。 – Marconline 2010-04-10 09:13:42