ABP的文档示例中,是这样的:
public class TaskAppService : ApplicationService, ITaskAppService { private readonly IRepository<Task> _taskRepository; public TaskAppService(IRepository<Task> taskRepository) { _taskRepository = taskRepository; }
如果这个AppService 需要多个 IRepository 呢? 一个一个注入吗?
查看仓储这个接口,发现是瞬时的生命周期。 每个仓储接口的实现类中,都会有Context。 这样一个请求,需要实例化这么多的Context?
另外从应用角度上看,每一个接口确实实现应该有独立的Context。Context的生命周期应该是Scope的
namespace Microsoft.Extensions.DependencyInjection { // // 摘要: // /// Extension methods for setting up Entity Framework related services in an // Microsoft.Extensions.DependencyInjection.IServiceCollection. /// public static class EntityFrameworkServiceCollectionExtensions { // // 摘要: // /// Registers the given context as a service in the Microsoft.Extensions.DependencyInjection.IServiceCollection. // /// You use this method when using dependency injection in your application, // such as with ASP.NET. /// For more information on setting up dependency injection, // see http://go.microsoft.com/fwlink/?LinkId=526890. /// // // 参数: // serviceCollection: // The Microsoft.Extensions.DependencyInjection.IServiceCollection to add services // to. // // optionsAction: // /// // /// An optional action to configure the Microsoft.EntityFrameworkCore.DbContextOptions // for the context. This provides an /// alternative to performing configuration // of the context by overriding the /// Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder) // method in your derived context. /// // /// // /// If an action is supplied here, the Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder) // method will still be run if it has /// been overridden on the derived context. // Microsoft.EntityFrameworkCore.DbContext.OnConfiguring(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder) // configuration will be applied /// in addition to configuration performed here. // /// // /// // /// In order for the options to be passed into your context, you need to expose // a constructor on your context that takes /// Microsoft.EntityFrameworkCore.DbContextOptions`1 // and passes it to the base constructor of Microsoft.EntityFrameworkCore.DbContext. // /// // /// // // contextLifetime: // The lifetime with which to register the DbContext service in the container. // // optionsLifetime: // The lifetime with which to register the DbContextOptions service in the container. // // 类型参数: // TContext: // The type of context to be registered. // // 返回结果: // /// The same service collection so that multiple calls can be chained. /// public static IServiceCollection AddDbContext<TContext>([JetBrains.Annotations.NotNull] this IServiceCollection serviceCollection, [JetBrains.Annotations.CanBeNull] Action<DbContextOptionsBuilder> optionsAction = null, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, ServiceLifetime optionsLifetime = ServiceLifetime.Scoped) where TContext : DbContext { return serviceCollection.AddDbContext<TContext, TContext>(optionsAction, contextLifetime, optionsLifetime); }
我们使用最原始的写法的话,应该只用一个Context.并且执行的逻辑也最清晰。
那这里的原因就是,一个AppService 中注入多个仓储接口是不合理的,这里应该使用一个仓储接口的Context 来引用到别的实体。或者在Domain层处理这些,但本质还是一样的。
2,在上面的例子中,Application 或Domain 里,经常会写Insert(entity)或InsertAndGetId(entity)
他们源码:
public override TEntity Insert(TEntity entity) { return Table.Add(entity).Entity; } public override TPrimaryKey InsertAndGetId(TEntity entity) { entity = Insert(entity); if (entity.IsTransient()) { Context.SaveChanges(); } return entity.Id; }
可以看出,InsertAndGetId是立即提交到数据库了,如果这个UOW 异常,还需要rollback。