我一直在玩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)我是否必须在服务中为这些存储库调用创建包装器方法?
2)在存储库中包含GetFiveLeggedAnimals方法和其他业务逻辑对我来说没有意义吗?
3)我可以在AnimalsService中实现IAnimalsRepository接口,然后调用基本方法(我意识到这是可能的,但我认为这是不好的做法)?
答案 0 :(得分:3)
1)我是否必须在服务中为这些存储库调用创建包装器方法?
大多数情况下,是的。通常,您希望为服务层中的域模型提供CRUD。这样,控制器不需要直接使用存储库(事实上,它永远不应该)。您可以在以后添加更复杂的逻辑,而无需更改外部代码。例如,考虑您想要实现新闻源。现在,每当插入一条五足动物时,你想创建一个新闻项目并将其推送给五足动物粉丝。另一个常见的例子是电子邮件通知。
2)在存储库中包含GetFiveLeggedAnimals方法和其他业务逻辑对我来说没有意义吗?
业务逻辑应位于服务层或域模型对象本身,并且仅在那里。事实上(见3),如果可能的话,我根本不会特别提供IAnimalRepository
。
例如,在NoSQL环境中,数据库驱动程序几乎是一个存储库。另一方面,当使用复杂的ORM映射和存储过程(部分biz逻辑在DB中)时,您实际上没有选择,只提供了解存储过程的显式接口。
如果可能的话,我会选择IRepository<T>
并使用查询对象模式。我认为 LINQ 也可以被认为是基于查询对象 / 存储库的模式。
3)我可以在AnimalsService中实现IAnimalsRepository接口,然后调用基本方法(我意识到这是可能的,但我认为这是不好的做法)?
要调用 base 方法,您必须从具体实现继承,例如:来自ConcreteAnimalsRepository
。
此外,如果您的服务直接或间接实现IAnimalsRepository
接口,它会使(未经过滤的)CRUD操作可供所有人使用。
我的看法:不要继承,聚合。服务层具有存储库,但它不是存储库本身:服务层处理所有其他应用程序逻辑(权限,通知),并且存储库是一个非常db层周围的薄包装。
作为一个极端的例子,如果禁止直接删除某些内容,并且在插入较新版本的某些内容时只允许该服务使用它,该怎么办?这可以在聚合时轻松构建。
答案 1 :(得分:1)
根据定义,存储库应该是一个类似于通用集合的类,用于抽象数据库交互。它将包含持久性的典型方法,如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
}
}
答案 2 :(得分:0)
我认为在Controller中使用简单的CRUD操作并且在Service类中有一个包装器是不好的,你应该将所有业务逻辑保留在服务层中,而不是在控制器中 例如,您想要创建一个新的Animal 在控制器中你将有方法
查看示例
// 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()等方法;您可以在服务类中使用包装器,我认为没问题。当你在控制器或Service类中编写一些代码时,我总是想给你一些忠诚,请记住你将如何测试这段代码 并且不要忘记SOLID