首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >仓库中的ViewModels

仓库中的ViewModels
EN

Stack Overflow用户
提问于 2017-07-05 12:19:46
回答 1查看 1.8K关注 0票数 1

我已经读到,存储库层不应该因为关注点的分离而处理ViewModels,而应该只处理模型。对于服务层也是如此(在我的例子中,这就是我的业务逻辑所在)。因此,控制器被留给处理ViewModels的总体。

我有一个模型类别:

代码语言:javascript
复制
public class Category
{

 public int ID { get; set; }

 public int? ParentCategoryID { get; set; }


 public virtual ICollection<Product> Products{ get; set; }

 public virtual ICollection<CategoryName> CategoryNames{ get; set; }
}

我在显示所有类别时使用了一个ViewModel CategoryListViewModel

代码语言:javascript
复制
public class CategoryListViewModel
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string ParentName { get; set; }
    }

我的观点是IEnumerable<...CategoryListViewModel>

我是这样从控制器中填充ViewModel的:

代码语言:javascript
复制
public ActionResult Index()
        {            
            IEnumerable<CategoryListViewModel> model;
            List<CategoryListViewModel> list = new List<CategoryListViewModel>();
            IEnumerable<Category> categoryList = categoryService.GetAllCategoriesList(RouteData);

            foreach (var item in categoryList)
            {
                CategoryListViewModel temp = new CategoryListViewModel()
                {
                    ID = item.ID,
                    Name = categoryService.GetCategoryName(RouteData, item.ID)                    
                };
                if (item.ParentCategoryID != null)
                {
                    temp.ParentName = categoryService.GetCategoryName(RouteData, (int)item.ParentCategoryID);
                }
                list.Add(temp);
            }
            model = list;
            return View(model);
        }

我的服务方法:

代码语言:javascript
复制
public IEnumerable<Category> GetAllCategoriesList(RouteData data)
        {
            LanguageService languageService = new LanguageService();
            Languages langEnum = languageService.LanguageStringToEnum(languageService.DetermineSelectedLanguage(data));

            IEnumerable<Category> allCategories = repository.getAllCategoriesTest();            

            return allCategories;
        }

public string GetCategoryName(RouteData data, int categoryId)
        {
            LanguageService languageService = new LanguageService();
            Languages langEnum = languageService.LanguageStringToEnum(languageService.DetermineSelectedLanguage(data));
            return repository.GetCategoryName(langEnum, categoryId);
        }

最后,我的存储库方法:

代码语言:javascript
复制
public IEnumerable<Category> getAllCategoriesTest()
        {
            return db.Category.ToList();
        }


public string GetCategoryName(Languages lang, int categoryId)
        {
            return db.CategoryName.Where(cn => cn.CategoryID == categoryId && cn.Language == lang).Select(cn => cn.Name).FirstOrDefault();
        }

在我看来,这种方法很糟糕。我的控制器已经不瘦了,我正在为这么简单的东西运行很多查询。

如果我允许ViewModels在我的存储库中,我会得到一个更干净的解决方案。

我的控制器方法:

代码语言:javascript
复制
public ActionResult Index()
        {
            return View(categoryService.GetAllCategories(RouteData));            
        }

服务方法:

代码语言:javascript
复制
public IEnumerable<CategoryListViewModel> GetAllCategories(RouteData data)
        {
            LanguageService languageService = new LanguageService();
            Languages langEnum = languageService.LanguageStringToEnum(languageService.DetermineSelectedLanguage(data));

            return repository.SelectAllCategories(langEnum);
        }

和储存库方法:

代码语言:javascript
复制
public IEnumerable<CategoryListViewModel> SelectAllCategories(Languages lang)
        {                        
            var categories = db.Category.Include(c => c.CategoryNames).Select(names => new CategoryListViewModel
            {
                ID = names.ID,
                Name = names.CategoryNames.Where(cn => cn.Language == lang).Select(cn => cn.Name).FirstOrDefault(),
                ParentName = db.CategoryName.Where(cn => cn.Language == lang && cn.CategoryID == names.ParentCategoryID)
                .Select(cn => cn.Name).FirstOrDefault()
            }).ToList();            
            return categories;                             
        }

这种方法,虽然违反了分离的关注,似乎是“更清洁”对我。

我的问题是,在查询方面,另一种方法不是更有效吗?此外,还有其他方法可以避免编写大量控制器方法而不执行那么多查询吗?在我看来,我好像错过了什么。

EN

回答 1

Stack Overflow用户

发布于 2017-07-05 13:10:23

首先,请记住,尽管名称中有" MVC“,ASP.NET MVC只是非常松散地实现MVC模式。MVC告诉您要有瘦控制器,因为模型是一个活动记录,它处理所有业务逻辑,包括围绕查询本身的业务逻辑。这不适用于ASP.NET MVC。在那里,您的模型实际上是DAL、服务层、实体和一个或多个视图模型的组合。这意味着,如果只将所有这些东西连接在一起,控制器就必须完成至少比Rails之类的控制器多一点的工作。

正如@Liam在上面的评论中所建议的,你最好的选择是工厂。这样,控制器实际上并不拥有如何将实体映射到视图模型的逻辑。当然,您仍然需要实际调用控制器中的工厂,但是逻辑仍然是抽象的。

另外,适当的服务层应该卷起本来在控制器中的逻辑。如果您需要该类别的本地化名称,则您的服务应该有一个方法,该方法将返回所有类别及其本地化名称。如果您必须多次访问您的服务,这就清楚地表明您没有为您的应用程序提供必要的端点。您可能需要引入一个DTO来处理这些数据,因为实体类可能没有适当的属性。然后,您将拥有一个将DTO映射到视图模型的工厂。

最后,对于它的价值,您的存储库是完全没有必要的。只需让您的服务直接与实体框架上下文交互即可。拥有一个存储库不会给您带来任何东西,只会给您额外的维护。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44926123

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档