【问题标题】:How to write an ASP.NET MVC repository interface containing multiple entities?如何编写包含多个实体的 ASP.NET MVC 存储库接口?
【发布时间】:2011-02-01 17:33:20
【问题描述】:

问题:

我是存储库模式的新手,我正在尝试使用它实现一个新的 ASP.NET MVC 应用程序。在实现“包含”/表示多个实体的存储库时,我有些困惑。我已经看到它声明每个实体不应该有一个存储库,而是每个聚合根有一个存储库。

如果我的聚合包含多个实体(或表,在我的物理模型中),那么这个聚合的基本 ASP.NET MVC 存储库是什么样的?

例子:

如果有一个具体的例子可以帮助我们,假设我们有一个包含聚合的应用程序,Employees。雇员聚合包含三个实体,由数据库中的三个表表示 - 雇员、雇员类型和就业状态。

Employee
======== 
EmployeeID (PK) 
EmployeeFullName 
EmployeeTypeCode (FK)

EmployeeTypes
============= 
EmployeeTypeCode (PK) 
EmployeeTypeCodeDescription

EmploymentStatus
================ 
EmployeeID (PK) 
EmploymentStatusCode (PK) 
EmploymentStatusStartDate (PK) 
EmploymentStatusEndDate

这种结构允许我们拥有员工,定义他们是什么类型的员工,并记录状态(受雇于一个职位、晋升到另一个职位、解雇、重新雇用等)。实际上,结构看起来与此不同,但让我们以它为例。

一个实体的不完整存储库(此示例基于 Steven Sanderson 在 Pro ASP.NET MVC 2 框架中给出的),它将为我们提供员工列表并允许我们保存一个员工可能是这个接口:

public interface IEmployeesRepository
{
    IQueryable<Employee> Employees { get; }
    void SaveEmployee(Employee employee);
}

还有这个实现(在这种情况下使用 Linq to SQL;它可以是 NHibernate 或实体框架):

using System;
using System.Data.Linq;
using System.Linq;
using MyApp.Domain.Abstract;
using MyApp.Domain.Entities;

namespace MyApp.Domain.Concrete
{
    public class SqlEmployeesRepository : IEmployeesRepository
    {
        private Table<Employee> employeesTable;
        public SqlEmployeesRepository(string connectionString)
        {
            employeesTable = (new DataContext(connectionString)).GetTable<Employee>();
        }
        public IQueryable<Employee> Employees
        {
            get { return employeesTable; }
        }

        public void SaveEmployee(Employee employee)
        {
            if (employee.EmployeeID == 0)
                employeesTable.InsertOnSubmit(employee);
            else if (employeesTable.GetOriginalEntityState(employee) == null)
            {
                employeesTable.Attach(employee);
                employeesTable.Context.Refresh(RefreshMode.KeepCurrentValues, employee);
            }
            employeesTable.Context.SubmitChanges();
        }
    }
}

【问题讨论】:

  • 感谢 Nick DeVore -- 我已经阅读过的那个问题的答案所引用的书和文章。不幸的是,似乎两者都没有谈论存储库中的多个实体。

标签: asp.net-mvc repository-pattern


【解决方案1】:

您的存储库看起来应该没有任何不同。它的界面根本不应该暴露您的聚合根具有任何特定子子实体的事实。显然,存储库的实现必须处理对这些子实体的更改,但您的 Employee 存储库呈现的接口应该与这些子实体完全没有。它们应该封装在 Aggregate Root 中。

【讨论】:

  • qstarin:我不确定我是否理解。你能在我给出的例子的背景下详细说明吗?假设一名员工被提拔,我们想要记录这一事实。为了正确实现 Repository 模式,我们可能希望在 Employee 存储库中使用 UpdateEmployeeStatus 方法,对吧,而不是使用自己的方法的新的 EmploymentStatus 存储库?
  • 没有。当然不。这是一种反模式,往往会导致贫血。它将您的域逻辑放在存储库中,但它属于实体。 UpdateEmployeeStatus 属于 Employee。员工负责修改自己的状态。并且存储库只是用来获取状态更改并将它们持久化(这就是为什么像 NHibernate 这样成熟的 ORM 如此有用,它们会自动处理获取实体中的状态更改)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
相关资源
最近更新 更多