MVC 将模型排除在服务层之外 - 并不总是可能的



>我有一个MVC项目,其中包括一个服务层。服务类将数据库实体对象返回到控制器,我使用这些控制器来构建传递给视图的模型。 通过这种方式,我的服务层对模型一无所知,我试图保持这种状态。

典型的服务层方法将返回 IQueryable,例如:

public IQueryable<Store> GetAll()
{
   return _context.Set<Store>();
}

但是,有时我需要从不存在数据库关系的 2 个数据库实体返回数据,并且由于服务层无法返回匿名类型,我最终返回了一个模型,我对此并不满意。

这方面的一个例子是:

public IEnumerable<CashDrawerModel> GetTillList(int? storeId)
{
var query = from c in _context.Set<CashDrawer>()
    where c.StoreId == storeId || storeId == null
    join cd in _context.Set<CashDrawerActivity>() on c.Id equals cd.CashDrawerId into joinedT
    from j in joinedT.DefaultIfEmpty()
     group joinedT by c into g
     select new CashDrawerModel
     {
      ...

我怎样才能避免这种情况?我担心保持这种分离是对的,还是它实际上表明糟糕的数据库设计并且需要重构?

我不认为这是一个糟糕的数据库设计,在将数据传递到视图之前必须查询多个数据库条目时,这是很常见的情况。有时,读取和写入操作之间的差异非常大,因此最好遵循命令查询分离原则。

所以如果我是你,我会做以下几件事:

  1. 需要时将读取模型添加到服务层。请注意,它们与视图模型无关。如果读取结果由上述多个数据库实体组成,则应使用它们。

  2. 添加相应的视图模型,并在控制器中执行服务层读取模型和视图模型之间的映射。这样,您就可以将服务层与表示层分开。如果视图模型被证明是服务层读取模型的精确副本,则在这种情况下,您可以跳过创建视图模型,而只需将读取模型传递给视图。但是,如果您需要添加一些与服务层无关的UI特定数据,则必须创建一个视图模型并进行映射。

  3. 想出一个好的命名召集。我更喜欢XXXReadModel作为服务层读取模型,XXXViewModel作为表示层视图模型。

因此,如果按照我上面描述的步骤进行操作,您应该CashDrawerReadModel这是服务层的一部分。然后,您应该拥有CashDrawerViewModel这是一个呈现层视图模型,并在控制器中执行两者之间的映射。您可以在此处跳过CashDrawerViewModel,以防它与CashDrawerReadModel相同,只需在视图中使用CashDrawerReadModel

希望对您有所帮助!

最新更新