我使用的是Repository和UoW模式。我的服务看起来像这样:
public class MyService : IService
{
private readonly IUnitOfWork<MyContext> unitOfWork;
private readonly IMyRepository myRepository;
public MyService(IUnitOfWork<MyContext> unitOfWork, IMyRepository myRepository)
{
this.unitOfWork = unitOfWork;
this.myRepository = myRepository;
}
//Methods...
}
在服务中,我需要使用其他实体(例如检查权限等)。
是否建议在服务中使用相关存储库或直接使用服务?
此外,对于每个用户,我们对每个CRUD操作都有权限(布尔值)。这些权限存储在数据库中。
是否应在控制器级别或服务级别检查权限?
答案 0 :(得分:5)
我的黄金法则是:
当您在UI中获得业务逻辑时创建服务,否则使用 直接存储库。
因此,如果您在UI中有此代码:
var user = repos.Get(1);
user.FirstName = txtFirstName.Text;
repos.Save(user);
我认为你很好。但如果你有类似的东西:
var user = userRepository.Get(1);
var accessChecker = authorizationRepository.GetForUser(id);
if (!accessChecker.MaySendEmail(user))
throw new SecurityException("You may not send emails");
var emailSender = new EmailSenderService();
emailSender.Send(user, txtDestination.Text, txtMessage.Text);
repos.Save(user);
您可能应该使用服务。
答案 1 :(得分:1)
不要使用您的UoW来包装您的数据库上下文。由于您的所有存储库都直接依赖于给定的上下文(或多或少,ofc),因此您的存储库可以包含在UoW中。有点像:
public interface IUnitOfWork<TContext> : IDisposable { }
public abstract class UnitOfWork<TContext> : IUnitOfWork<TContext> {
private readonly TContext _context;
protected TContext Context { get{ return _context; } }
protected UnitOfWork(TContext context){
_context = context;
}
}
public interface IMyDbUnitOfWork : IUnitOfWork<MyContext>{
public ICarRepository Cars { get; }
public IOwnerRepository Owners { get; }
}
public class MyDbUnitOfWork : UnitOfWork<MyContext>, IMyDbUnitOfWork{
public MyDbUnitOfWork():base(new MyContext()){}
private ICarRepository _cars;
public ICarRepository Cars {
get{
return _cars ?? (_cars = new CarRepository(Context));
}
}
private ICarRepository _owners;
public IOwnerRepository Owners {
get{
return _owners ?? (_owners = new OwnerRepository(Context));
}
}
}
public class MyService : IService
{
private readonly IMyDbUnitOfWork _unitOfWork;
public MyService(IMyDbUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
//Methods...
}
显然你可以创建或多或少的通用,但我相信这应该足以传递我的观点。
作为一个说明,由于我通常使用IoC框架,因为不同的生活方式,我的服务会收到IUnitOfWorkFactory
。
对于权限问题,它实际上取决于您希望拥有多少控制权以及您希望应用程序具有用户友好性。通常是两者的混合。您的应用程序应该知道您的用户是否有权访问该屏幕,但是如果您必须相应地禁用按钮。由于您也必须阻止,如果由于任何原因,用户可以调用您的服务方法,您不能允许它。 为了解决这个问题,我不会通过CRUD操作进行过滤,而是通过服务操作进行过滤,拦截每个服务调用,这样可以很容易地将我的权限映射到用户界面,因为通常是按钮操作和服务之间的1对1关系动作。
答案 2 :(得分:0)
我认为使用存储库就好了。我不会为每个回购发明一个服务层。 存储库用于抽象数据访问,服务层用于封装业务逻辑,但是根据最近的趋势,我发现这有点过分。如果服务层充当控制器但没有尝试将一对一映射到每个实体或存储库,那么服务层就没有问题。
答案 3 :(得分:0)
我通常使用来自UI的服务,而这些服务又使用存储库。我还发现有一些域对象可以在服务中封装可重用逻辑。
我这样做是为了不是服务相互调用并获得循环引用,而是服务使用公共域对象。这样可以避免循环引用和人们在整个地方复制和粘贴相同的代码。如果需要,此域对象可以使用存储库。