当依赖项需要运行时值时,如何注入依赖项?

莱斯特

我正在实现ASP.NET MVC应用程序,并且需要实现带有存储库模式的工作单元我的实现设计如下:

  • UnitOfWork对象负责根据需要发布COMMITs和ROLLBACKs。
  • UnitOfWork对象包含Transaction从内部数据库连接中获取的属性。该对象为内的操作提供了原子性UnitOfWork
  • UnitOfWork对象包含存储库作为在运行时注入的属性。
  • 每个存储库都需要提供创建以支持原子性IDbTransaction对象UnitOfWork

因此,现在我发现自己处于一种奇怪的境地,UnitOfWork即必须注入需要UnitOfWork自身属性的存储库才能实例化。所以我的问题是:我该怎么做?还是必须更改设计中的某些内容?

我目前正在使用SQL Server,并且使用Dapper进行SQL调用。另外,我正在考虑使用Autofac作为DI框架。

到目前为止,我所做的是实现UOW和示例存储库。代码如下。

IRepository.cs

public interface IRepository<TObj, TKey>
{
    Task<TObj> DetallesAsync(TKey id);
    Task<TKey> AgregarAsync(TObj obj);
}

DbRepository.cs

public abstract class DbRepository
{
    private readonly IDbConnection _connection;
    private readonly IDbTransaction _transaction;

    protected IDbConnection Connection
    {
        get => _connection;
    }

    protected IDbTransaction Transaction
    {
        get => _transaction;
    }

    public DbRepository(IDbTransaction transaction)
    {
        _transaction = transaction;
        _connection = _transaction.Connection;
    }
}

RolRepository.cs

public class MSSQLRolRepository : DbRepository, IRolRepository
{
    public MSSQLRolRepository(IDbTransaction transaction)
        : base(transaction)
    {

    }

    public async Task<int> AgregarAsync(Rol obj)
    {
        var result = await Connection.ExecuteScalarAsync<int>(MSSQLQueries.RolAgregar, param: obj, transaction: Transaction);
        return result;
    }

    public async Task<Rol> DetallesAsync(int id)
    {
        var param = new { Id = id };
        var result = await Connection.QuerySingleOrDefaultAsync<Rol>(MSSQLQueries.RolDetalles, param: param, transaction: Transaction);
        return result;
    }

    public async Task<Rol> DetallesPorNombreAsync(string nombre)
    {
        var param = new { Nombre = nombre };
        var result = await Connection.QuerySingleOrDefaultAsync<Rol>(MSSQLQueries.RolDetallesPorNombre, param: param, transaction: Transaction);
        return result;
    }

    public async Task<Rol[]> ListarAsync(int pagina, int itemsPorPagina)
    {
        var param = new { Pagina = pagina, ItemsPorPagina = itemsPorPagina };
        var result = await Connection.QueryAsync<Rol>(MSSQLQueries.RolListar, param: param, transaction: Transaction);
        return result.ToArray();
    }

    public async Task<Rol[]> ListarTodosAsync()
    {
        var result = await Connection.QueryAsync<Rol>(MSSQLQueries.RolListar, transaction: Transaction);
        return result.ToArray();
    }
}

IUnitOfWork.cs

public interface IUnitOfWork : IDisposable
{
    IDbTransaction Transaction { get; }
    IDenunciaRepository DenunciaRepository { get; }
    IUsuarioRepository UsuarioRepository { get; }
    IRolRepository RolRepository { get; }
    void Commit();
    void Rollback();
}

MSSQLUnitOfWork.cs

public class MSSQLUnitOfWork : IUnitOfWork
{
    private bool _already_disposed = false;
    private IDbConnection _connection;
    private IDbTransaction _transaction;
    private IDenunciaRepository _denuncia_repository;
    private IUsuarioRepository _usuario_repository;
    private IRolRepository _rol_repository;

    public IDbTransaction Transaction
    {
        get => _transaction;
    }

    public IDenunciaRepository DenunciaRepository
    {
        get => _denuncia_repository;
    }

    public IUsuarioRepository UsuarioRepository
    {
        get => _usuario_repository;
    }

    public IRolRepository RolRepository
    {
        get => _rol_repository;
    }

    public MSSQLUnitOfWork()
    {
        var connection_string = ConfigurationManager.ConnectionStrings["MSSQL"].ConnectionString;
        _connection = new SqlConnection(connection_string);
        _connection.Open();
        _transaction = _connection.BeginTransaction();
        //TODO: Crear repos con transacción
    }

    public void Commit()
    {
        _transaction.Commit();
    }

    public void Rollback()
    {
        _transaction.Rollback();
    }

    protected virtual void Dispose(bool disposeManagedObjects)
    {
        if (!_already_disposed)
        {
            if (disposeManagedObjects)
            {
                _transaction?.Dispose();
                _connection?.Dispose();
            }
            _already_disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }
}
斯拉夫迪米尔

我向您推荐3种不同的东西。

  1. 在实例化UnitOfWork的存储库中启动,提交和回滚数据事务-我建议的最低建议

  2. 创建一个Service类,您可以在其中创建UnitOfWork的实例,并将该实例或DBContext传递给您在事务中涉及的存储库

  3. 在知道当前DBContext的UnitOfWork类内创建Repository实例,然后您可以从UnitOfWork访问存储库操作,并在同一上下文中启动和结束事务。更多推荐

就像是:

UnitOfWorkInstance.MyRepositoryA.AddAsync(...);
UnitOfWorkInstance.MyRepositoryB.AddAsync(...);
UnitOfWorkInstance.Commit();

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Guice运行时依赖项参数重新注入

Google Guice运行时依赖项注入

使用依赖项注入在运行时确定实现

使用Google Guice在运行时注入依赖项

如何在运行时控制OSGi中的依赖项注入

如何使用简单的注入器在运行时更改依赖项

如何在运行时动态更改依赖项

ASP.NET Core依赖项注入:服务在运行时使用Func委托解析

将运行时依赖项注入到nix包中

温莎城堡在嵌套类中注入依赖项,根接口在运行时解析

在运行时初始化依赖项

安全删除“未使用的”运行时依赖项

gradle 从运行时依赖项中排除特定的 jars

Spring从依赖项中选择运行时实现

在Python轮子中包括运行时依赖项

OSGi中仅运行时依赖项的最佳实践

指定Nix包运行时依赖项

Jar依赖项编译时间和运行时

Firebase依赖项在运行时导致错误

在Apache Spark中指定运行时依赖项

构建依赖项和运行时依赖项有什么区别

Eclipse为什么将Maven运行时依赖项转换为编译依赖项?

gradle将传递性运行时依赖项包含为编译依赖项

当项目没有自己的类时,Gradle 的“实现”依赖项是运行时范围的

如何在SBT中将依赖项设置为运行时(以模仿Maven中的运行时作用域)?

如何在gradle jar任务生成的jar中包括运行时依赖项

如何覆盖Robolectric运行时依赖项存储库URL?

如何获取具有gradle项目的所有运行时依赖项的文件?

Visual Studio 2015运行时依赖项或如何摆脱Universal CRT?