asp.net – 模型,ViewModels,MVC 3应用程序中的DTO

我有一个Web解决方案(在VS2010中)有两个子项目:

>持有Model类的域(通过实体框架映射到数据库表)和服务(除了其他东西)负责CRUD操作
>引用域项目的WebUI

对于我创建的第一个页面,我已经使用了Domain项目中的Model类,直接作为我强类型视图中的Model,因为类很小,我想显示修改所有的属性

现在我有一个页面,只能使用相应域模型的所有属性的一小部分。我通过在我的Service类中使用查询结果的投影来检索这些属性。但是我需要投入一个类型 – 这里有我可以想到的解决方案的问题:

>我介绍了现在在WebUI项目中的viewmodels,并将IQueryables和EF数据上下文从服务公开到WebUI项目。然后我可以直接投入这些viewmodels。
>如果我不想公开IQueryable和EF数据上下文,我将viewmodel类放在Domain项目中,那么我可以直接从Service类返回viewmodels作为查询和预测结果。
>除了WebUI项目中的viewmodels之外,我还介绍了将数据从Service类中的查询中移动到viewmodels的数据传输对象。

解决方案1和2看起来像同样的工作量,我倾向于倾向于将所有数据库问题保留在单独的项目中。但是不知何故在域项目中有View-Models是错误的。

解决方案3听起来像更多的工作,因为我有更多的类创建和关心Model-DTO-viewmodel映射。我也不明白DTO和viewmodels之间的区别是什么。 viewmodel不是我想要显示的我的Model类的选定属性的集合吗?它们不会包含与DTO相同的成员吗?为什么要区分viewmodels和DTO?

这三种解决方案中的哪一种是优选的,有什么好处和缺点?还有其他选择吗?

感谢您提前收到意见!

编辑(因为我可能有一个太长的文本墙,并被要求代码)

示例:我有一个客户实体…

public class Customer
{
    public int ID { get; set; }
    public string Name { get; set; }
    public City { get; set; }
    // ... and many more properties
}

…并且想要创建一个显示(并且可能允许编辑)列表中的客户名称的视图。在一个服务类中,我通过投影来提取我需要的数据:

public class CustomerService
{
    public List<SomeClass1> GetCustomerNameList()
    {
        using (var dbContext = new MyDbContext())
        {
            return dbContext.Customers
                .Select(c => new SomeClass1
                             {
                                 ID = c.ID,Name = c.Name
                             })
                .ToList();
        }
    }
}

那么有一个带有动作方法的CustomerController。这怎么样?

这样(a)…

public ActionResult Index()
{
    List<SomeClass1> list = _service.GetCustomerNameList();
    return View(list);
}

…或更好这样(b):

public ActionResult Index()
{
    List<SomeClass1> list = _service.GetCustomerNameList();

    List<SomeClass2> newList = CreateNewList(list);

    return View(newList);
}

关于上面的选项3,我会说:SomeClass1(住在Domain项目)是一个DTO,而SomeClass2(住在WebUI项目中)是一个viewmodel。

我想知道区分两个班级是否有意义。为什么我不会总是选择(a)控制器动作(因为它更容易)?除了DTO(SomeClass1)之外,还有理由引入viewmodel(SomeClass2)吗?

解决方法

introduce viewmodels which live in the
WebUI project and expose IQueryables
and the EF data context from the
service to the WebUI project. Then I
Could directly project into those
viewmodels.

很难遇到这样的问题,您很快就会遇到使用EF尝试“展平”模型的问题。当我有一个如下所示的Commentviewmodel类时,我遇到类似的东西:

public class Commentviewmodel
{
    public string Content { get; set; }
    public string DateCreated { get; set; }
}

以下EF4查询投影到Commentviewmodel将不会像couldn’t translate the ToString() method into SQL

var comments = from c in DbSet where c.PostId == postId 
               select new Commentviewmodel() 
               { 
                   Content = c.Content,DateCreated = c.DateCreated.ToShortTimeString() 
               };

使用像Automapper这样的东西是一个不错的选择,特别是如果你有很多转换。但是,您也可以创建自己的转换器,基本上将您的域模型转换为视图模型。在我的情况下,我创建了我自己的扩展方法,将我的Comment域模型转换为我的Commentviewmodel,如下所示:

public static class viewmodelConverters
{
    public static Commentviewmodel ToCommentviewmodel(this Comment comment)
    {
        return new Commentviewmodel() 
        { 
            Content = comment.Content,DateCreated = comment.DateCreated.ToShortDateString() 
        };
    }

    public static IEnumerable<Commentviewmodel> ToCommentviewmodelList(this IEnumerable<Comment> comments)
    {
        List<Commentviewmodel> commentModels = new List<Commentviewmodel>(comments.Count());

        foreach (var c in comments)
        {
            commentModels.Add(c.ToCommentviewmodel());
        }

        return commentModels;
    }
}

基本上我做的是执行标准的EF查询来带回一个域模型,然后使用扩展方法将结果转换为视图模型。例如,以下方法说明了用法

public Comment GetComment(int commentId)
{
    return CommentRepository.GetById(commentId);
}

public Commentviewmodel GetCommentviewmodel(int commentId)
{
    return CommentRepository.GetById(commentId).ToCommentviewmodel();
}

public IEnumerable<Comment> GetCommentsForPost(int postId)
{
    return CommentRepository.GetCommentsForPost(postId);
}

public IEnumerable<Commentviewmodel> GetCommentviewmodelsForPost(int postId)
{
    return CommentRepository.GetCommentsForPost(postId).ToCommentviewmodelList();
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要讲解了“WPF如何实现带筛选功能的DataGrid”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“WPF...
本篇内容介绍了“基于WPF如何实现3D画廊动画效果”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这...
Some samples are below for ASP.Net web form controls:(from http://www.visualize.uk.com/resources/asp
问题描述: 对于未定义为 System.String 的列,唯一有效的值是(引发异常)。 For columns not defined as System.String, the only vali
最近用到了CalendarExtender,结果不知道为什么发生了错位,如图在Google和百度上找了很久,中文的文章里面似乎只提到了如何本地化(就是显示中文的月份)以及怎么解决被下拉框挡住的问题,谈
ASP.NET 2.0 page lifecyle ASP.NET 2.0 event sequence changed a lot since 1.1. Here is the order: App
静态声明: &#39; Style=&quot;position: relative&quot; AppendDataBoundItems=&quot;True&quot;&gt; (无 或 空 或
以下内容是从网络上搜集资料,然后整理而来的。不当之处,请不吝指教。(The following were from network, and edited by myself. Thanks in a
Imports System Imports System.Reflection Namespace DotNetNuke &#39;*********************************
Ok so you have all seen them: “8 million tools for web development”, “5 gagillion tools that if you
以下内容来源于: http://blog.csdn.net/cuike519/archive/2005/09/27/490316.aspx 问:为什么Session在有些机器上偶尔会丢失? 答:可能和
以下文章提到可以用“http://localhost/MyWebApp/WebAdmin.axd”管理站点: ---------------------------------------------
Visual Studio 2005 IDE相关的11个提高开发效率的技巧 英文原创来源于: http://www.chinhdo.com/chinh/blog/20070920/top-11-vis
C#日期格式化 from: http://51xingfu.blog.51cto.com/219185/46222 日期转化一 为了达到不同的显示效果有时,我们需要对时间进行转化,默认格式为:2007
from: http://www.nikhilk.net/UpdateControls.aspx Two controls that go along with the UpdatePanel and
Open the report in the Designer. In the ToolBox, select/expand the &quot;Report Items&quot; section.
from: http://drupal.org/node/75844 Do this: find which TinyMCE theme you are using. For the sake of
asp.net中给用户控件添加自定义事件 用户控件中定义好代理和事件: public delegate void ItemSavedDelegate(object sender, EventArgs
在Windows版本的Safari中浏览以下的页面。 http://www.asp.net/AJAX/Control-Toolkit/Live/Calendar/Calendar.aspx Calen
http://aspnet.4guysfromrolla.com/articles/021506-1.aspx By Scott Mitchell Introduction When creating