C# 带有服务层的存储库和UoW模式
我正在使用存储库和UoW模式。我的服务如下所示:C# 带有服务层的存储库和UoW模式,c#,repository-pattern,unit-of-work,C#,Repository Pattern,Unit Of Work,我正在使用存储库和UoW模式。我的服务如下所示: public class MyService : IService { private readonly IUnitOfWork<MyContext> unitOfWork; private readonly IMyRepository myRepository; public MyService(IUnitOfWork<MyContext> unitOfWork, IMyRepository m
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...
}
公共类MyService:IService
{
私有只读IUnitOfWork;
私有只读IMyRepository myRepository;
公共MyService(IUnitOfWork、IMyRepository myRepository)
{
this.unitOfWork=unitOfWork;
this.myRepository=myRepository;
}
//方法。。。
}
在服务中,我需要使用其他实体(例如检查权限等)
建议使用服务中的相关存储库还是直接使用服务
此外,对于每个用户,我们对每个CRUD操作都有权限(布尔值)。这些权限存储在数据库中
权限检查应该在控制器级别还是在服务级别进行?我认为使用存储库很好。我不会为每个repo发明一个服务层。
存储库用于抽象数据访问,服务层用于封装业务逻辑,但随着最近的趋势,我发现这有点过头了。如果服务层充当控制器,但不要尝试将一对一映射到每个实体或repo,那么使用服务层就可以了。我认为使用存储库就可以了。我不会为每个repo发明一个服务层。 存储库用于抽象数据访问,服务层用于封装业务逻辑,但随着最近的趋势,我发现这有点过头了。如果服务层充当控制器,但不要试图将一对一映射到每个实体或回购,则使用服务层是可以的。我的黄金法则是: 当您在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);
您很可能应该改用服务。我的金科玉律是:
当您在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);
您可能应该改用服务。不要使用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...
}
公共接口IUnitOfWork:IDisposable{}
公共抽象类UnitOfWork:IUnitOfWork{
私有只读TContext\u上下文;
受保护的TContext上下文{get{return}
受保护的UnitOfWork(TContext上下文){
_上下文=上下文;
}
}
公共接口IMyDbUnitOfWork:IUnitOfWork{
公共电子储蓄车{get;}
公共IOOwnerRepository所有者{get;}
}
公共类MyDbUnitOfWork:UnitOfWork,IMyDbUnitOfWork{
公共MyDbUnitOfWork():基(新MyContext()){}
私家车;
公共储蓄车{
得到{
归还车辆??(\u车辆=新的运输地点(上下文));
}
}
私人Icarepository所有者;
公共所有权或保留所有权人{
得到{
返回_owners???(_owners=newownerrepository(上下文));
}
}
}
公共类MyService:IService
{
私有只读IMyDbUnitOfWork(单位工作);;
公共MyService(IMyDbUnitOfWork unitOfWork)
{
_unitOfWork=unitOfWork;
}
//方法。。。
}
很明显,你可以创建这个或多或少的通用,但我相信这应该足以通过我的观点。
值得注意的是,由于我通常使用IoC框架,我的服务会收到IUnitOfWorkFactory
,因为生活方式不同
对于权限问题,这实际上取决于您希望拥有多少控制权,以及您希望应用程序对用户的友好程度。通常是两者的混合。你的应用程序应该知道你的用户是否有权访问屏幕,但也知道你是否必须相应地禁用按钮。由于您还必须防止这种情况,如果用户出于任何原因可以调用您的服务方法,那么您不能允许它。
为了解决这个问题,我不按CRUD操作进行过滤,而是按服务操作进行过滤,拦截每个服务调用,这使得将我的权限映射到用户界面很容易,因为按钮操作和服务操作之间通常是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...
}
公共接口IUnitOfWork:IDisposable{}
公共抽象类UnitOfWork:IUnitOfWork{
私有只读TContext\u上下文;
受保护的TContext上下文{get{return}
受保护的UnitOfWork(TContext上下文){
_上下文=上下文;
}
}
公共接口IMyDbUnitOfWork:IUnitOfWork{
公共电子储蓄车{get;}
公共IOOwnerRepository所有者{get;}
}
公共类MyDbUnitOfWork:UnitOfWork,IMyDbUnitOfWork{
公共MyDbUnitOfWork():基(新MyContext()){}
私家车;
公共储蓄车{
得到{
归还车辆??(\u车辆=新的运输地点(上下文));
}
}
私人Icarepository所有者;
公共所有权或保留所有权人{
得到{
返回_owners???(_owners=newownerrepository(上下文));
}
}
}
公共类MyService:IService
{
私有只读IMyDbUnitOfWork(单位工作);;
公共MyService(IMyDbUnitOfWork unitOfWork)
{
_unitOfWork=unitOfWork;
}
//方法。。。
}
很明显,你可以创建这个或多或少的通用,但我相信这应该足以通过我的观点。
值得注意的是,由于我通常使用IoC框架,我的服务会收到IUnitOfWorkFactory
,因为生活方式不同
为了