Фабрика единиц работы с кратными DbContext - PullRequest
0 голосов
/ 16 июня 2020

Я создаю новое проектное решение для одного приложения, в котором уже создана база данных, и в этой базе данных у нас есть 3 версии для каждой таблицы (заархивированная, удаленная и активная).

Это пример кода, который у нас есть сегодня

public class MyEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public enum eStatus
{
    Active,
    Archived,
    Deleted,
}

public class MyContext : DbContext
{
    public eStatus Status { get; }

    public MyContext(DbContextOptions<MyContext> options, eStatus status = eStatus.Active)
        : base((DbContextOptions)options)
    {
        this.Status = status;
    }

    public virtual DbSet<MyEntity> MyEntities { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity((Action<EntityTypeBuilder<MyEntity>>)(entity =>
        {
            switch (this.Status)
            {
                case eStatus.Archived:
                    entity.ToTable("MyEntity_Archived");
                    break;
                case eStatus.Deleted:
                    entity.ToTable("MyEntity_Deleted");
                    break;
                case eStatus.Active:
                    entity.ToTable("MyEntity");
                    break;
            }
            entity.HasKey(e => e.Id as object);
        }));
    }
}

public interface IMyRepository
{
    List<MyEntity> Get();
}

public class MyRepository : IMyRepository
{
    private readonly MyContext _context;

    public MyRepository(MyContext context)
    {
        _context = context;
    }

    public List<MyEntity> Get()
    {
        return _context.MyEntities.ToList();
    }
}

public interface IUnitOfWork
{
    IMyRepository MyRepository { get; }
}

public class UnitOfWork : IUnitOfWork
{
    private readonly MyContext _myContext;

    public UnitOfWork(MyContext myContext)
    {
        _myContext = myContext;
    }

    private IMyRepository _myRepository;

    public IMyRepository MyRepository => _myRepository ??= new MyRepository(_myContext);
}

public interface IUnitOfWorkFactory
{
    IUnitOfWork Build(eStatus status = eStatus.Active);
}

public class UnitOfWorkFactory : IUnitOfWorkFactory
{
    private readonly IServiceProvider _serviceProvider;

    public UnitOfWorkFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }
    public IUnitOfWork Build(eStatus status = eStatus.Active)
    {
        var context = _serviceProvider.GetServices<MyContext>().First(x => x.Status == status);

        return new UnitOfWork(context);
    }
}

public static class DependencyInjectionExtensions
{
    public static void RegisterServices(this IServiceCollection services, IConfiguration configuration)
    {
        var myContextOptions = new DbContextOptionsBuilder<MyContext>();
        myContextOptions.UseSqlServer(configuration.GetConnectionString("MyConnectionString"));

        services.AddTransient(x => new MyContext(myContextOptions.Options, eStatus.Active));
        services.AddTransient(x => new MyContext(myContextOptions.Options, eStatus.Archived));
        services.AddTransient(x => new MyContext(myContextOptions.Options, eStatus.Deleted));
        services.AddScoped<IUnitOfWorkFactory, UnitOfWorkFactory>();
    }
}

Проблема в том, что с этим кодом мы не можем использовать UnitOfWork и репозитории из DI. Мы должны создать новый экземпляр внутри метода Build, а затем создать экземпляр репозитория внутри класса UnitOfWork.

Есть ли лучший способ или лучшие практики для этого, поскольку у нас уже есть база данных, созданная с помощью это конфигурации?

...