2012-04-03 23 views
1

我剛開始使用視圖&我的MVC web應用程序中的域模型設計,但得到了問題在哪裏執行計算和其他視圖相關的操作。我會嘗試下面的例子。視圖和域模型,在哪裏執行計算

我的域模型(LINQ2SQL)

public class Product 
{ 
    public int Id; 
    public string Name; 
} 

UserCount性能視圖模型,我想計算。

public class ProductViewModel 
{ 
    public int Id; 
    public string Name; 
    public int UserCount; 
} 

我的控制器動作看起來像

public ActionResult _SelectionClientSide_Products() 
{ 
    IQueryable<Product> products = _repository.GetProducts(true); 
    var model = Mapper.Map<IEnumerable<Product>, IEnumerable<ProductViewModel>>(products);         
    return View(model); 
} 

我查詢使用存儲庫法數據,並得到IQueryable<Product>並將其映射到ProductViewModel列表。但是我還需要執行另一個查詢操作來計算每個查詢產品的用戶數,並將所有值分配給ProductViewModel。我應該遵循什麼樣的設計來實現這一點?

Products -> Orders - > Users 

編輯

我已決定刪除AutoMapper因爲它給了大於收益的問題,並創建了自己的生成器包含的一切我所需要的關係。我進行字段分配並添加計算。

public ActionResult _SelectionClientSide_Products() 
    {   
     Data = new ProductViewModelBuilder(_repository).Build(); 
     return View(Data); 
    } 

namespace PC.Models 
{ 
      public class ProductViewModel 
      { 
       public int Id { get; set; } 
       public string Name { get; set; } 
       public int UsersCount { get; set; } 
      } 

      public class ProductViewModelBuilder 
      { 
       private readonly IDataAccess _repository; 

       public ProductViewModelBuilder(IDataAccess repository) 
       { 
        _repository = repository; 
       } 

       public IQueryable<ProductViewModel> Build() 
       { 
        return _repository.GetProducts().Select(p=> new ProductViewModel 
                     { 
                      Id = p.Id, 
                      Name = p.Name, 
                      UsersCount = _repository.CountUsers(p.Id) 
                     });   
       } 

      } 
     } 

回答

0

在我看來,當你的控制器開始它的模型設置時,應該沒有更多的「邏輯」或與模型交談。有一個「建設者」再次查詢模型是不好的做法。不是真的「打破」MVC模式,但仍然是不好的做法。您的ViewModel依賴於您的DAL。壞壞男孩。 :)

如果您必須運行另一個查詢,那麼應該封裝在原始查詢中。不要調用_repository.GetProducts,而要調用不同的方法,它不僅可以獲得產品,還可以獲得計數。如有必要,創建一個DTO。

那麼你的控制器看起來應該像:

public ActionResult _SelectionClientSide_Products() 
{ 
    var someDto = _repository.GetProductsAndUserCount(true); 
    var model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);         
    return View(model); 
} 

個人而言,我去了超過專業的人通用庫,因爲我不希望與50個簽名一個IProductRepository接口。我選擇了LINQ IEnumerable<T>擴展(又名「管道和過濾器」),它允許構建複雜的查詢並保留在我的域中。

所以我上面的版本是:

public ActionResult _SelectionClientSide_Products() 
{ 
    var someDto = _productRepository.Find().WithSomeCondition(true).ToSomeDto(); 
    var model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);         
    return View(model); 
} 

在一個側面說明,爲什麼這麼說呢AutoMapper使你更多的問題,好處是什麼? AutoMapper節省了大量的重複代碼。如果你知道如何正確使用它,那是你最好的朋友。在我當前的應用程序中介紹最重要的NuGet包。

+0

我讀過,如果在一個View模型中只需要這些字段一次,那麼在Domain模型中創建其他字段是不好的做法。如果您的示例_repository.GetProductsAndUserCount方法返回Domain模型(不確定但看起來如此),但默認情況下沒有UserCount字段。那麼你是否建議在域模型中創建計算字段(我使用linq2sql,並且這種情況下的域部分類將被擴展)?但正如我所說我已經讀過,這是不實際的。 – Tomas 2012-04-03 11:00:41

+0

@Tomas - 這是一個DTO。所以它的目的是包裝一個或多個域對象,以便它可以傳送到應用程序堆棧中。那種不好的做法如何?您的ProductViewModelBuilder是不好的做法。 – RPM1984 2012-04-03 21:16:35

+0

我使用Linq2SQL,我的DTO是由Linq2Sql構建器自動生成的類。 Product(DTO)類沒有UserCount屬性,我可以使用Partial類擴展它,但它不合理,因爲在其他地方使用了相同的Product類。所以我應該創建另一個DTO類,類似於Linq2Sql生成的Product DTO,並添加UserCount屬性,然後使用var someDto = _productRepository.Find()。WithSomeCondition(true).ToSomeDto();? – Tomas 2012-04-04 10:48:58

相關問題