更改服务是在运行时通过 .Net Core DI 容器注入为作用域还是瞬态?

我们的应用程序中有几个依赖于 Entity Framework 6 的类。因此,我们将我们的资金注入DbContext到各个领域。但是,某些模块实现了多线程方法,需要DbContext将其作为瞬态服务注入以防止任何线程问题。其他模块能够通过简单地调用接收SaveChanges相同共享的任何子模块或模块来串在一起并批量保存DbContext。但是,这种方法需要DbContext添加为范围服务。


除了构建一些简单地继承自 my 的子类或接口之外DbContext,是否有任何方法可以动态确定类是否获取给定服务的作用域版本或瞬态版本?


子类化上下文的示例可能类似于


public class TransientDbContext : DbContext {}

public class ScopedDbContext : DbContext {}


// in services

services.AddTransient<TransientDbContext>();

services.AddScoped<ScopedDbContext>();

这是可行的,但我正在寻找一些更动态的东西,我可以在其中传递一个参数来指示一个类应该使用共享上下文。


对于一些额外的上下文,图像我有以下接口


public interface IRepository<TEntity> 

{

    void Add(TEntity entity);

    Task SaveAsync(CancellationToken token = default);

}


public interface IUserManager 

{

    Task AddAsync(User user, bool commitChanges = true, CancellationToken = default);

}


public interface IUserPhoneNumberManager 

{

    Task AddAsync(UserPhoneNumber number, bool commitChanges, CancellationToken token = default)

}

在幕后,我可能有以下具体实现


public class UserRepository<User> : IRepository<User>

{

    private readonly DbContext _dbContext;

    public UserRepository(DbContext dbContext)

    {

        _dbContext = dbContext;

    }


    public void Add(User entity) 

    {

        _dbContext.Users.Add(entity);

    }


    public Task SaveAsync(CancellationToken token = default)

    {

        return _dbContext.SaveChangesAsync(token);

    }

}


public class UserPhoneNumberRepository<UserPhoneNumber> : IRepository<UserPhoneNumber>

{

    private readonly DbContext _dbContext;

    public UserRepository(DbContext dbContext)

    {

        _dbContext = dbContext;

    }


    public void Add(UserPhoneNumber entity) 

    {

        _dbContext.UserPhoneNumbers.Add(entity);

    }


    public Task SaveAsync(CancellationToken token = default)

    {

        return _dbContext.SaveChangesAsync(token);

    }

}

现在,在某些情况下,我希望向底层存储库注入单一范围的上下文,而其他时候我想要一个瞬态上下文。这些瞬态上下文在使用时显然会提交自己的更改。但作用域上下文会将其更改作为单个单元提交。


神不在的星期二
浏览 113回答 1
1回答

拉风的咖菲猫

我认为你的问题的核心在于以下观察:某些模块实现多线程方法,需要将 DbContext 作为瞬态服务注入,以防止任何线程问题。这意味着您的应用程序代码本身负责处理多线程;您可能正在启动新的线程或任务。这是你应该防止的事情。相反,只有您的Composition Root应该了解多线程性并且应该派生出新线程。这集中了有关线程安全的知识。但不仅如此,许多组件都不是线程安全的,只有组合根应该知道哪些组件是线程安全的,哪些不是。组件本身应该始终以顺序方式调用其依赖项,并假设该依赖项只有一个实例。这意味着当您开始并行操作时,您应该返回到组合根以让它解析新的对象图。然后,组合根可以决定将组件的新实例注入到图中(例如您的DbContext)。DbContext当您应用这种工作方式时,您将不再需要有瞬态版本和作用域版本。
打开App,查看更多内容
随时随地看视频慕课网APP