我是ASP.NET MVC的新手,我正试图了解一些设计概念。我目前坚持的一件事是如何(最好)处理如下所述的情况。
假设我有一个页面需要渲染许多“部分”。例如,在左侧有一个数据驱动的列表,然后列表中的选定项目在页面的另一个部分中显示另一个列表。为了更好地理解,我们建议左手列表是电影类别列表,另一个列表显示该类别中包含的电影列表,以及各种电影细节。
现在,我有一些形式的ORM,例如Entity Framework,LINQ to SQL或者将tblCategory和tblMovie数据库表分别映射到Category和Movie实体的任何形式。这些实体位于MyMVCApp.Data.Entities命名空间中。然后,我使用位于MyMVCApp.Data命名空间中的存储库模式来封装针对这些实体的查询(通过LINQ)以返回我们的模型实体。
这是我的第一个问题所在。存储库是否应该返回视图模型实体或域实体,然后将其扩展为生成视图模型实体?在我天真的想法中,我看到从ORM返回的实体只是包含业务逻辑的域实体的数据的容器。那么肯定应该有一个abstration?
无论如何,回到我的场景。现在让我们假设我希望提出在本文开头描述的两个部分。我假设这里应该发生的是我的域实体模型将包含类别及其相关电影的列表。所以像List一样,每个List都包含一个List。
此模型已在某处填充。这是我的第二个问题。假设我的上述假设是正确的,它只是从ORM返回的数据实体。现在我有一个名为MyMVCApp.Core.Model(或类似名称)的名称空间/项目,其中包含一些域实体,例如前一段中提到的Movie和Category实体。这些实体是否有方法从ORM中检索数据并填充自己?或者存储库是否检索这些填充的实体模型?另一个问题是,如果我的ORM中有一个电影和客户实体,那么域名实体的名称是否可以接受?
最后,我假设控制器现在具有填充的Category和Movie对象列表,并将其传递回视图。我猜最好将开头描述的每个部分作为部分视图并将填充的模型传递给每个部分?因此,它可能是IndexController,它检索填充的CategoryMovies实体,将其传递给Categories部分视图和Movies部分视图。然后我需要以某种方式确定所选的类别(quesrystring?)并在视图中显示该类别中的相应电影列表。
好的,所以如果有人在我的谣言中达到这一点,我会深深鞠躬。我希望我已经足够详细地解释了我的混乱思想和问题,以便某人能够提供某种启示。感谢收听! : - )
答案 0 :(得分:2)
既然你没有提到它,我会假设你是DDD概念的新手。 DDD通过将逻辑放在它所属的位置来补充MVC中的“M”。并且,我认为这里可以应用很多金额。
在严格的DDD格式中,我会将您的电影示例用作聚合根(DDD概念)。在Movie中,您将拥有获取与Movie直接相关的类别和相关实体的业务逻辑(方法)(即Categories-this-movie-belongs-in)。这假定您要显示的“类别”列表是此电影所在的类别列表。
public class Movie
{
private IList<Category> _categories;
public IList<Category> FetchCategories()
{
// you can lazy-load here, use Linq-to-Sql, etc.
return _categories;
}
public void AddCategory(Category c)
{
_categories.Add(c);
}
}
当然,如果您没有身份标识,可以将类别视为价值对象(VO,DDD概念)。
现在,更有趣的是,如果您确实希望在您的类别上保留一个身份,将它们视为具有多个实体的聚合根以及与其他VO等的关系。在这种情况下,您可能希望利用服务的DDD概念将两个聚合组合到您想要传递给Controller的请求模型中。这允许您围绕加载类别创建业务规则。
public class Movie
{...}
public class Category
{...}
public class MovieCategory : Movie
{
private IList<Category> _categories;
public IList<Category> Categories
{
get
{
return _categories;
}
internal set
{
_categories = value;
}
}
}
public class MovieCategoryService
{
public MovieCategory FetchMovieCategoryByMovieId(int id)
{
MovieCategory mc = _movieRepository.FetchMovie(id);
// do some logic here, some checks, etc
// to obtain your Categories list. Maybe querystring?
IList<Category> cats = ...;
mc.Categories = cats;
return mc;
}
}
这个概念是你现在在这个MovieCategoryService的域层中有逻辑来处理这些关系的复杂创建,或者使用Factories创建复杂类型。
这为您提供了一个可以传递给不同View和PartialViews的模型。
原始帖子的最后一步是如何将其添加到视图中。我一直在玩这个问题的ViewModel方法。动态创建ViewModel,或者作为类创建ViewModel,并挂起此ViewModel上的所有实体。最近的StackOverflow问题触及了这个概念。 ViewModel Best Practices
我已经将模型直接传递给了Views,我现在正在尝试这种方法。它确实可以清理,因为您的DOmain模型确实应该与页面上的“逻辑”断开连接。我发现自己在想,“当然。我需要根据这个ID来填充这个部分视图。猜猜这意味着实体上的另一种方法。”使用ViewModel方法从域模型中删除逻辑/思想,并将其放在它所属的位置 - 在您正在微调视图/部分视图的应用程序/ UI层中。
答案 1 :(得分:1)
首先,我认为你应该开始使用一个简单的项目并尝试你在长期问题中描绘的各种场景:)。没有什么是一成不变的,你可以使用任何与数据层和服务相关的架构,或者你喜欢的任何东西!
或者存储库是否检索这些填充的实体模型?
我会说是的。您的控制器会从服务中获取这些内容并获取它们,填充所有内容并将它们移动到视图中以便显示。
我猜最好将开头描述的每个部分作为部分视图并将填充的模型传递给每个部分?
我再次认为你走在正确的轨道上;)。
答案 2 :(得分:1)
将视图模型实体提供给视图而不是整个域实体本身是一个不错的主意,从而为视图提供仅需要处理的所需内容
首先从你的域中返回一个类别列表,然后构建一个电影视图,它将类别名称作为这样的参数
- <Host>/Movies/Comedy
- <Host>/Movies/Horror
反过来显示属于该特定类别的电影