11

我對MVC模式不是很熟悉。你能告訴我以下三種管制員行動哪一種更好?謝謝:)在控制器中使用linq查詢是不是很好的做法?

(1)具備動作查詢:

public ActionResult List() 
{ 
    var query = repository.Query().Where(it => it.IsHandled).OrderBy(it => it.Id); 
    // ... 
} 

(2)具有在服務查詢:

public ActionResult List() 
{ 
    var items = service.GetHandledItemsOrderById(); 
    // ... 
} 

(3)在行動中有順序:

public ActionResult List() 
{ 
    var items = service.GetHandledItems().OrderBy(it => it.Id); 
    // ... 
} 

如果我們選擇(1),那麼我們在控制器中有太多的業務邏輯?

如果我們選擇(2),可能會有很多服務方法,如GetXXXByYYY()

如果我們選擇(3),我們爲什麼封裝Where(it => it.IsHandled)但不
OrderBy(it => it.Id

任何想法?

回答

3

這取決於。 :)

我的看法:

我喜歡讓我的服務鬆動,以儘量減少重複的代碼。我也是管道和過濾器的粉絲。

這就是我會做(和DO做)。

服務

public ICollection<Item> GetHandledItems<TKey>(OrderingOptions<Item, TKey> orderingOptions) 
{ 
    return repository 
     .Query() 
     .WhereHandled() 
     .WithOrdering(orderingOptions) 
     .ToList();  
} 

ItemFilters.cs

public static IQueryable<Item> WhereHandled(this IQueryable<Item> source) 
{ 
    return source.Where(it => it.IsHandled); 
} 

public static IOrderedQueryable<T> WithOrdering<T, TKey>(
    this IQueryable<T> source, 
    OrderingOptions<T, TKey> orderingOptions) 
{ 
    return orderingOptions.SortDescending 
     ? source.OrderByDescending(orderingOptions.OrderingKey) :              
     source.OrderBy(orderingOptions.OrderingKey); 
} 

OrderingOptions.cs

public class OrderingOptions<T,TKey> 
{ 
    public OrderingOptions(Expression<Func<T,TKey>> orderingKey, bool sortDescending = false) 
    { 
     OrderingKey = orderingKey; 
     SortDescending = sortDescending; 
    } 

    public Expression<Func<T,TKey>> OrderingKey { get; private set; } 
    public bool SortDescending { get; private set; } 
} 

這樣喲ü可以在控制器中指定的順序:上面和選項3之間

var items = service.GetHandledItems(new OrderingOptions(it => it.Id)); 

差異:

  • 以上返回控制器之前物化序列。選項3不會,這是很危險的(你可能最終將查詢返回到View並打破MVC模式)。
  • 通用「訂購」POCO,可以在任何地方使用,並保持您的查詢D-R-Y。
  • 服務變成愚蠢,並且簡單地在存儲庫和控制器(這是它應該做的,IMO)之間的緩衝區。邏輯(例如過濾器)抽象到一個地方。

HTH

+0

謝謝。如果「GetHandledItems()」返回一個集合(不是IQueryable),我們就不能對查詢執行投影。它會影響性能。 –

+0

@Dylan - 因此,在執行查詢之前,在服務中進行預測,可以通過內聯或通過其他管道方法執行,例如:'return repo.Query()。WhereHandled()。WithOrdering()AsSomeProjectedType()' – RPM1984

+0

這**輝煌的** RobCon vid MVC管道和過濾器:http://www.asp.net/mvc/videos/aspnet-mvc-storefront-part-3-pipes-and-filters – RPM1984

4

我確定意見可能會有所不同,但我學會了儘可能多地在服務中保留業務邏輯。 3將是我的選擇。 1,你已經發現了這個問題。使用2時,您將在服務中引入顯示優先級。使用3時,您可以根據需要處理顯示首選項。如果要向業務層引入另一個接口,則需要通過選擇2來執行潛在的不必要的代碼迭代。請參見下面的示例。

+0

頁面需要表明被標識處理訂單項目。爲什麼「顯示已處理(已處理)的項目」是業務邏輯,應該在服務中,而「按ID排序顯示項目」是顯示偏好? –

+0

我認爲「顯示處理項目」和「按ID顯示項目順序」都是顯示偏好?所以我們應該選擇1? –

+1

我覺得我的問題應該是:(1)是「哪裏(it => it.IsHandled)」商業邏輯? (2)是「OrderBy(it => it.Id)」的商業邏輯嗎? –

相關問題