MVC3通过服务展示存储库功能
本文关键字:存储 功能 服务 MVC3 | 更新日期: 2023-09-27 17:58:34
我一直在玩asp.net MVC3,一直在努力决定将我的业务逻辑放在哪里。我现在已经决定使用一个服务层:
public class AnimalsService : IAnimalsService
{
private readonly IAnimalsRepository _animalsRepository;
public AnimalsService(IAnimalsRepository animalsRepository)
{
_animalsRepository = animalsRepository;
}
public IQueryable<Animal> GetFiveLeggedAnimals()
{
...
}
}
控制器看起来像这样:
public class AnimalsController : Controller
{
private readonly IAnimalsService _animalsService;
public AnimalsController(IAnimalsService animalsService)
{
_animalsService = animalsService;
}
public ViewResult ListFiveLeggedAnimals()
{
var animals = _animalsService.GetFiveLeggedAnimals();
return View(animals);
}
}
我在存储库中有基本的CRUD逻辑(All、Find、UpdateOrInsert、Delete)。如果我想在我的控制器中使用这些CRUD方法:
1) 我必须在服务中为这些repository调用创建包装器方法吗?
2) 对我来说,仅仅在存储库中包含GetFiveLeggedAmals方法和其他业务逻辑不是更有意义吗?
3) 我可以在AnimalsService中实现IAnimalsRepository接口,然后调用基本方法吗(我意识到这是可能的,但我认为这是一种糟糕的做法)?
1) 我必须在服务中为这些repository调用创建包装器方法吗?
大多数情况下,是的。通常,您希望在服务层中为您的域模型提供CRUD。这样,控制器就不需要直接使用存储库(事实上,它永远不应该)。您可以稍后添加更复杂的逻辑,而不必更改外部代码。例如,假设您想要实现一个新闻提要。现在,每次插入一只五条腿的动物时,你都想创建一个新闻项目,并将其推送给五条腿动物的粉丝。另一个常见的例子是电子邮件通知。
2) 对我来说,仅仅在存储库中包含GetFiveLeggedAmals方法和其他业务逻辑不是更有意义吗?
业务逻辑应该在服务层或域模型对象本身中,并且仅在那里。事实上(见3),如果可能的话,我根本不会专门提供IAnimalRepository
。
例如,在NoSQL环境中,数据库驱动程序几乎是存储库。另一方面,当使用复杂的ORM映射和存储过程(biz逻辑的一部分在DB中)时,您实际上别无选择,只能提供了解存储过程的显式接口。
如果可能的话,我会选择IRepository<T>
并使用查询对象模式。我认为LINQ也可以被视为基于查询对象/存储库的模式。
3) 我可以在AnimalsService中实现IAnimalsRepository接口,然后调用基本方法吗(我意识到这是可能的,但我认为这是一种糟糕的做法)?
要调用base方法,必须从具体实现继承,例如从ConcreteAnimalsRepository
继承。
此外,如果您的服务直接或间接地实现了IAnimalsRepository
接口,它将使(未经过滤的)CRUD操作对每个人都可用。
我的看法是:不要继承,聚合。服务层有存储库,但它本身并不是:服务层处理所有额外的应用程序逻辑(权限、通知),存储库是数据库层的一个非常薄的包装器。
举个极端的例子,如果直接删除某个内容是被禁止的,并且在插入对某个内容的新修订时,只有服务才被允许使用它,该怎么办。?这可以在聚合时轻松构建。
Repository根据定义应该是一个抽象DB交互的类的泛型集合。它将包含典型的持久性方法,如Get(object id), Add(T), Remove(T)
,并可能实现IQueryable<T>
。
该服务看起来像下面的代码。
public class AnimalsService : IAnimalsService
{
private readonly IRepository<Animal> _repository;
public AnimalsService(IRepository<Animal> repository)
{
_repository = repository;
}
public IEnumerable<Animal> GetFiveLeggedAnimals()
{
// animal specific business logic
}
}
我认为在Controller中使用简单的CRUD操作并在Service类中使用包装器是不好的,您应该将所有业务逻辑保留在服务层中,而不是控制器中例如,你想创建一个新的动物在控制器中,您将有方法
看看的例子
// not good design
public ActionResult Create(AnimalInput input)
{
Animal animal = new Animal { Name = input.Name}; // set the other propreties
// if you have a CRUD operations in service class you will call
animalService.UpdateOrInsert(animal);
}
// better disign
public ActionResult Create(AnimalInput input)
{
animalService.Create(input.Name);
}
在服务类实现中遵循
public void Create(string name)
{
Animal animal = new Animal { Name = input.Name};
animalRepository.UpdateOrInsert(animal);
}
对于GetAll或GetFiveLeggedAnimals()等方法;你可以在服务类中有包装器,我认为可以。当你在控制器或服务类中编写一些代码时,我想给你一个答案——记住你将如何测试这些代码不要忘记SOLID