当前位置: 首页 > 知识库问答 >
问题:

实体VS域模型VS视图模型

吕利
2023-03-14

在这个话题上有数百个类似的问题。但我仍然感到困惑,我希望得到专家的建议。

我们正在使用ASP开发一个应用程序。NETMVC4和EF5以及我们的是DB优先的方法。

我们在一个单独的项目中有数据层,该项目是一个类库,包含其中定义的所有实体。然后是用所有存储库和域模型定义的业务层(这是正确使用的术语)。然后是表示层。

目前我们还没有定义任何视图模型,我们使用的是与视图模型相同的BL域模型。在这种方法中,一个映射就足够了。

实体

但对我来说,这不是一个好的设计。我更喜欢在表示层中定义视图模型,并使用域模型在表示层和业务层之间进行通信。在BL,将域对象转换为数据实体,并与DAL通信。使用这种方法,我必须使用映射两次。

视图模型

我的领域模型真的有必要吗?我不能使用我的实体与表示层通信。如果我在表示层中引用实体,会有任何影响吗?如果有什么样的影响?

共有3个答案

冯良才
2023-03-14

引入额外类的主要好处是分离关注点:

  • 表示层:显示信息和数据输入,包括实现此目的的任何前处理和后处理,例如格式化。
  • 域/业务/应用程序逻辑:这里完成了实际工作
  • 持久层:存储和检索数据

这可以通过ViewModels和Domain实体的两个模型类来实现。与使用类似于持久化实体的单独模型类对域逻辑进行建模不同,在使用域实体的服务类中实现它。域实体最多应该具有处理其自身属性的逻辑(例如,保持两个属性的组合值处于有效状态)。如果一个用例影响多个域实体,则在服务类中对该用例进行建模。如果将逻辑直接放在实体类中管理实体之间的关系,代码很快就会变得不可维护(相信我,我试过了)。

我不建议使用持久性实体作为视图模型,因为这会将显示问题(例如[DisplayName])与持久性问题(例如[ForeignKey])混为一谈。

葛深
2023-03-14

我不是专家,但我会在这个话题上分享我的50美分。

我想和大家分享一下你对忽略视图模型的担忧。

使用视图模型,您可以:

  1. 仅从域模型中选择所需的数据
  2. 以正确的方式将所需数据格式化到演示文稿中(例如,将价格小数(100.00)格式化为字符串(€100.00))
  3. 可以在视图模型上使用DataAnnotation

所以,我也认为这是一个糟糕的设计,但其他人可能会有不同的看法。

记住,业务层对视图模型一无所知,所以应该在控制器中映射它。

我会简单地开始,使用POCO作为域模型,可以用ORM或NoRM持久化。对于世界上开发的大多数软件来说,它不会对您的系统造成太大伤害,而且非常简单。

将来,如果出于某种原因开始使用web服务,可能需要考虑使用DTO(数据传输对象)进行远程调用。在那里,你可以做的是有另一个层,负责将你的域模型映射到所需的DTO。该层将仅用于远程调用(web服务),保留演示文稿的视图模型。

劳夕
2023-03-14

我认为你只是在定义每一层是什么以及它在解决方案中扮演什么角色方面遇到了问题。

您的数据层就是您的数据库/SharePoint列表/。csv文件/excel工作表。。。你明白了,它只是存储数据的地方,可以是任何格式。所以请记住,数据层只不过是数据。

// ----------------------------
//    Data tier
//        - MySQL
//        - MS SQL
//        - SharePoint list
//        - Excel
//        - CSV
//        - NoSQL
// ----------------------------

该层抽象出您的数据源,并提供一个API,您的应用程序的其余部分可以在其中与数据源交互。

假设我们的数据源是一个MS SQL数据库,并且我们正在使用实体框架来访问数据。您将试图抽象出数据库和实体框架,并为每个实体建立一个数据存储库

我们在MSSQL数据库中有一个客户表。客户表中的每个客户都是一个实体,并且在您的C#代码中表示为这样。

通过使用repository模式,我们可以抽象出数据访问代码的实现,这样将来,如果数据源发生更改,应用程序的其余部分就不会受到影响。接下来,我们需要在数据访问层中有一个客户存储库,其中包括添加删除查找字节等方法。提取任何数据访问代码。下面的例子是如何实现这一点。

public interface IEntity
{
    int Id { get; set; }
}

public class Customer : IEntity
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime RegistrationDate { get; set; }
}

public interface IRepository<TEntity> where TEntity : class, IEntity
{
    TEntity FindById(int id);
    
    void Add(TEntity entity);
    
    void Remove(TEntity entity);
}

public class CustomerRepository : IRepository<Customer>
{
    public Customer FindById(int id)
    {
        // find the customer using their id
        return null;
    }
    
    public void Add(Customer customer)
    {
        // add the specified customer to the db
    }
    
    public void Remove(Customer customer)
    {
        // remove the specified customer from the db
    }
}

数据访问层位于数据层和业务逻辑之间。

// ----------------------------
//    Business logic
// ----------------------------

// ----------------------------
//    Data access layer
//        - Repository 
//        - Domain models / Business models / Entities
// ----------------------------

// ----------------------------
//    Data tier
//        - MySQL
//        - MS SQL
//        - SharePoint list
//        - Excel
//        - CSV
//        - NoSQL
// ----------------------------

业务层构建在数据访问层之上,不处理任何数据访问问题,而是严格地处理业务逻辑。如果业务需求之一是防止从英国境外发出订单,那么业务逻辑层将处理此问题。

表示层只是表示您的数据,但如果您不小心表示哪些数据,以及允许发布哪些数据,那么您将面临很多麻烦,这就是为什么使用视图模型很重要的原因,因为视图模型是表示层关心的问题,表示层不需要了解您的域模型,它只需要了解视图模型。

那么什么是视图模型...它们只是为每个视图量身定制的数据模型,例如,注册表将包括RegistrationViewModel,公开这些典型属性。

public class RegistrationViewModel
{
    public string Email { get; set; }
    public string Password { get; set; }
    public string ConfirmPassword { get; set; }
}

表示层还处理输入验证,因此例如验证键入的电子邮件地址是否具有正确的格式,或者输入的密码是否匹配是表示层关注的问题,而不是业务关注,并且可以通过使用Data Annoations来处理。

public class RegistrationViewModel
{
    [Required]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Compare("ConfirmPassword")
    public string Password { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string ConfirmPassword { get; set; }
}

使用视图模型很重要的原因是因为业务模型属于业务层,它们包含应该保持私有的数据。例如,如果您要在JSON响应中公开域模型,它会公开用户的整个数据,他们的名字他们的地址,因为您没有选择公开什么和不公开什么,而是使用任何看起来有效的东西。

这里我还应该指出,域模型实体模型之间存在差异。这里已经有了一个更详细的答案

我会保持简短:

  • 异常管理
  • 视图模型到域模型的映射。
    • 汽车制造商

 类似资料:
  • null 根据我所读到的内容,使用QueryDsl或JPA元模型的主要优点之一是类型安全。 但即使使用标准API也可以实现类型安全。(我将JPA与eclipselink一起使用) 有两个变体 我同意第一个版本,在这个版本中,我将sql作为字符串传递,但没有获得类型安全。但是在第二个版本中,我得到了类型安全。还是我漏了什么?谁能用一个例子来解释使用条件是不安全的。 QueryDsl和JPA静态元模型

  • 但是,是我所说的“域”类--我的模型可以自由引用和使用的东西。我不希望我的域和模型层知道/依赖于这样一个事实,即应用程序是使用JavaFX显示的。 我认为模型/域在这方面应该保持纯净,这是对的吗?如果是这样,使用JavaFX最好的方法是什么?例如,我是否应该以某种方式为我的域对象编写适配器类,以便用来表示它们?

  • 本文向大家介绍wpf 视图模型,包括了wpf 视图模型的使用技巧和注意事项,需要的朋友参考一下 示例 视图模型是MV VM中的“ VM” 。这是一个充当中介的类,将暴露model(s)给用户界面(视图),并处理来自视图的请求,例如单击按钮引发的命令。这是一个基本的视图模型: 构造函数创建一个Customer模型对象,并将其分配给CustomerToEdit属性,以使视图可见。 构造函数还创建一个R

  • 问题内容: 对于MySQL / SQL的分配,我需要创建2个不同的表以显示 强实体和弱实体之间 的 差异 。 有人可以向我展示我如何做到这一点的例子吗? 我知道一个强实体可以不存在另一个实体而存在,而对于一个弱实体却不是这样。因此,例如,一个强大的实体如下所示: ? 但是我不确定如何创建一个显示差异的表。 问题答案: 想象一下带有以下各列的表: 该表如下所示: 现在,每个 Manager都是一个E

  • 8.4.2 模型与视图 复杂应用程序经常可以分解成两个部分:核心逻辑和用户界面。程序的核心逻辑部分称 为模型(model),它负责为应用问题建模,管理应用问题的数据和行为,并对来自用户界面 的数据请求或数据更新指令进行响应。程序的用户界面部分称为视图(view),它负责显示模 型的当前数据状态,响应用户的交互动作。模型和视图是相互独立的,可以分开设计和测试, 从而简化程序结构、降低设计难度,这称为

  • 我想制作一个表模型,它通过列表存储实体。像这样; 在扩展了AbstractTableModel的实体表模型中,方法getValueAt(int row,int column)应该根据行和列的值返回实体字段的值。行表示列表中的实体编号,列表示实体对象中的字段编号。但问题是,当我使用下面的代码;