我在成长过程中遇到了一个有趣的问题。现在,我使用一个与数据库无关的工作层单元来抽象我的ASP.MVC 4 web应用程序中实际数据库依赖项中的数据访问。
实现工作单元接口的每个单独的数据库项目都知道我的业务模型(直接进入或离开数据库的模型)。我不太清楚我对这种方法的看法,但这不是我要问的问题。
我是否应该使用像AutoMapper这样的解决方案将业务模型转换为/从域模型--传递到视图并用于任何不应该访问数据库字段(即ID)的工作中的模型?
例如,在我的BusinessModels项目中,我有以下类
BusinessModels
/UserAccounts/
User.cs
- ID
- Username
- HashedPassword
- Salt
UserSettings.cs
- IsSubscribedToNewsletter
- AllowDirectEmails将这些用户和UserSettings模型绑定到使用AutoMapper这样的单个模型有意义吗?
MyProject
/DomainModels/
User.cs
- Username
- HashedPassword
- Salt
- IsSubscribedToNewsletter
- AllowDirectEmails为了表达自己的观点?
这个问题也扩展到了非MVC项目,但是我觉得当我正在开发一个MVC项目时,在这个标签中问它会更有意义。
TLDR是否有必要映射业务模型/实体来查看模型,或者是否提供了不必要的抽象层?如果是这样的话,存储库是包含业务模型还是视图模型(这些模型自动映射到底层的业务模型)?
发布于 2013-12-10 16:19:20
您可以将视图模型用于两种不同的事情:
(我知道,第二个问题是有争议的。但是,使用视图模型来实现这一点并不奇怪)
GET操作的模型需要所有必要的属性来呈现视图:
假设您有一个可以属于一个UserGroup的用户。
在这种情况下,如果要编辑用户,模型需要:
我会用这样的模型:
public class EditUserModel
{
public User User {get;set;}
public SelectList UserGroups {get;set;}
}如您所见,我直接将用户添加为属性。但是我没有将类别列表作为属性添加,因为我不需要整个类别列表,并在视图中包含它们的所有属性。此外,如果您对控制器进行单元测试,则可以验证SelectList是否如预期的那样(如果在视图中创建用户组列表,则无法做到这一点)。
但是,如果您不需要视图中用户的所有属性怎么办?是否值得删除用户属性,并为名称、电子邮件、JoinedData、Active.?我认为答案是否定的。假设您添加/删除或重命名了一些用户实体属性。如果视图模型中有单独的属性,那么在更新视图之前,还必须对它们进行更改。而且,如果您依赖于自动映射(自动映射器、值注入器),那么如果您犯了一些错误,您甚至都不会意识到。
我还说过,视图模型可以用于将数据回发到控制器。所以你可以这么做:
[HttpPost]
public ActionResult Edit(EditUserModel userModel)如果这样做,模型绑定将使用窗体控件中的值填充userModel。所以你会得到一个半空的模型。在这种情况下,UserGroups列表将为null,并且,取决于您编辑的用户属性的数量,用户还可以拥有许多空/非初始化属性。
为了避免出错,在某些情况下,建议创建一个不同的模型(可能还包括辅助类),以明确预期将发布到模型中的内容。
例如,如果您有一个操作来显示整个用户数据,但它只允许更改其密码,则可以创建一个具有两个属性的类: password和PasswordConfirmation。
在这种情况下,POST的视图模型只能具有密码和PasswordConfirmation。并导出具有此继承属性的GET模型,以及用户组和用户列表。
为什么要继承和不使用独立的类?仅仅因为当您使用类似于Html.TextBoxFor(m => m.User.Name)的东西时,Model将能够设置用户属性的Name属性,但前提是post操作的参数具有相同的结构。也就是说,如果get的视图模型具有以下结构:
public ChangePasswordModel
{
public string Password {get;set;}
public string PasswordConfirmation {get;set;}
// extra properties, like the list of user groups, the user data...
}这个职位的模型有这样的结构:
public PostedChanegPasswordModel
{
public User User {get;set;}
}Html.TextBoxFor(m => m.EditedUser.Name)呈现的输入的内容不会绑定到PostedEditViewModel的User.Name。
但如果你做这个:
public EditUserModel : PostedEditUserModel
{
// extra properties, like the list of user groups
}数据将被绑定,不会有任何问题。
一般情况下,您必须小心您使用的模型,以张贴和获取。我建议使用和蜜罐一样多的不同的视图模型。
何时使用自动属性映射到全新的视图和不同的模型?
您一定有一个非常强烈的理由有不同的视图模型。这可能是在外部(即先设计)启动应用程序的结果,或者是因为一个团队在实现业务logie之前或期间正在开发UI。
在这种情况下,您可以发现视图模型的类和视图本身已经定义好了,它们与实体非常相似,但并不完全相等。这是一个例子,当我认为它可以是好的使用映射器。
使用不同类的另一个原因是将接口与逻辑分离。但这通常只发生在前一种情况下。
发布于 2013-12-10 12:59:14
考虑到视图模型,我将它们视为您希望使用的数据的摘要。
因此,以您的示例为例,您的视图模型将包含来自User和UserSettings类的数据。假设您有一个名为UserData.cshtml的视图,那么我会将其编码如下:
public class UserDataViewModel
{
public string Username { get; set; }
public bool AllowDirectEmails { get; set; }
// etc ...
}
public ActionResult UserData()
{
var viewModel = new UserDataViewModel();
viewModel.UserName = "Whatever";
viewModel.AllowDirectEmails = false;
// Or however you get the data for the user.....
return View(viewModel)
}希望你能明白。因此,将外部类中的信息合并到一个viewmodel类中是正确的。基本地将视图模型类中的所有内容连接在一起。
我将viewmodel类命名为与它将要用于的视图相同。这可以帮助文档,并使新开发的代码更容易遵循。
https://stackoverflow.com/questions/20495136
复制相似问题