何时实例化存储库?它的寿命是什么



在DDD中,是应用层,使用存储库从数据库中获取数据,调用域的方法,然后调用存储库来持久化数据。类似的东西:

public void MyApplicationService()
{
Order myOrder = _orderRepository.Get(1);
myOrder.Update(data);
_orderRepository.Commit();
}

在本例中,存储库是一个类变量,它在服务的构造函数中实例化,因此它的生命周期就是类的生命周期。

但我想知道,为我想做的每个操作实例化一个存储库是否会更好,以缩短使用寿命,因为如果不是这样,如果我将该类用于许多操作,那么存储库将有许多实体,也许它不需要更多。

所以我在想这样一个解决方案:

public void MyApplicationService()
{
OrderRepository myOrderRepository = new OrderRepository(_options);
Order myOrder = myOrderRepository.GetOrder(1);
myOrder.Update(data);
myOrderRepository.Commit();
myOrderRepository.Dispose();
}

所以每次我都需要做一个新的实例。

因此,总之,我想了解不同的解决方案以及决定存储库使用寿命的优缺点。

谢谢。

存储库的建议使用寿命为一个业务事务

您的第二个代码补丁在这方面是正确的,但它有一个缺点:在ApplicationServiceOrderRepository类之间创建了强依赖关系。使用您的代码,您无法隔离这两个类以便分别对它们进行单元测试。此外,无论何时更改OrderRepository的构造函数,都需要更新ApplicationService类。如果OrderRepository需要参数来构造,那么您必须构造它们(这意味着引用它们的类型和基类型(,尽管这是OrderRepository的实现细节(数据持久性存储访问需要(,而应用程序服务层不需要。

由于这些原因,大多数现代程序开发都依赖于一种称为依赖注入(DI(的模式。使用DI,您可以指定ApplicationService类依赖于OrderRepository类的一个实例,或者更好的是OrderRepository类实现的接口IOrderRepository。通过在ApplicationService构造函数中添加一个参数来声明依赖关系:

public interface IOrderRepository : IDisposable
{
Order GetOrder(int id);
void Commit();
}
public class ApplicationService
{
private readonly OrderRepository orderRepository;
public ApplicationService(IOrderRepository orderRepository)
{
this.orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
}
public void Update(int id, string data)
{
Order myOrder = orderRepository.Get(id);
myOrder.Update(data);
orderRepository.Commit();
}
}

现在DI库负责构造OrderRepository并将实例注入ApplicationService类中。如果OrderRepository有自己的依赖项,库将首先解析它们并构建整个对象图,这样您就不必自己这样做了。您只需要告诉您的DI库,您希望每个引用的接口有什么具体的实现。例如C#中的

public IServiceCollection AddServices(IServiceCollection services)
{
return services.AddScoped<IOrderRepository,OrderRepository>();
}

在对代码进行单元测试时,可以将OrderRepository的实际实现替换为mock对象,例如Mock<IOrderRepository>或您自己的MockOrderRepository实现。测试中的代码就是生产中的代码,所有的连接都由DI框架完成。

大多数现代DI库都支持对象生存期管理,包括瞬态(始终解析新对象(、单例(始终重用同一对象(或作用域(每个作用域都有一个实例(。后者用于隔离每个业务事务的对象实例,无论何时启动业务事务,都使用单例ScopeFactory创建作用域:

public class UpdateOrderUseCase : UseCase
{
private readonly IScopeFactory scopeFactory;
public UpdateOrderUseCase(IScopeFactory scopeFactory) // redacted
public void UpdateOrder(int id, string data)
{
using var scope = scopeFactory.CreateScope();
var orderRepository = scope.GetService<IOrderRepository>();
var order = orderRepository.Get(id);
order.Update(data);
orderRepository.Commit();
// disposing the scope will also dispose the object graph
}
}

当您实现REST服务时,该事务通常对应于一个HTTP请求。现代框架,如asp.net核心,将自动为每个HTTP请求创建作用域,并在稍后的框架内部使用它来解析依赖关系图。这意味着您甚至不必自己处理ScopeFactory。

最新更新