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接口,然后调用基本方法吗(我意识到这是可能的,但我认为这是一种糟糕的做法)?

MVC3通过服务展示存储库功能

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