简体   繁体   中英

Net Core: Execute Dependency Injection with Xunit for Unit of Work Pattern and DBContext

I am trying to conduct dependency injection for a Base Repository with Unit of Work pattern, we are using generic repository (which was decided from company architect).

For some reason nothing is saving, just wondering what is proper way to correlate DBContext with Unit of Work, in dependency injection below. Currently received empty values below when testing, nothing is saving in Entity framework.

It can save with Regular Dbcontext, but cannot save values with Unit of Work pattern after testing.

In Xunit test.cs, seems like I need to pass TestContext as parameter to UnitofWork Constructor, not sure how to in Dependency injection, receiving errors,

Unit of Work

public class UnitOfWork : IUnitOfWork
{
    private readonly DbContext context;
    public UnitOfWork(DbContext context)
    {
        this.context = context;
    }

    public DbSet<TEntity> DBSet<TEntity, TPrimaryKey>() where TEntity : class, IEntity<TPrimaryKey> => context.Set<TEntity>();

    public void SetAsModified<TPrimaryKey>(IEntity<TPrimaryKey> entity) => Task.Run(() => context.Entry(entity).State = EntityState.Modified);

    public async Task Save()
    {
        await context.SaveChangesAsync();
    }

    // IDisposable pattern support
    private bool disposed = false;
    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed && disposing)
        {
            context.Dispose();
        }
        this.disposed = true;
    }

Base Repository:

public class BaseRepository<T, TPrimaryKey> : IRepository<T, TPrimaryKey> where T : class, IEntity<TPrimaryKey>
{
    private readonly IUnitOfWork unitOfWork;
    protected virtual DbSet<T> DbSet { get; }
    protected IQueryable<T> All => DbSet.AsNoTracking();

    public IUnitOfWork UnitOfWork => unitOfWork;

    public BaseRepository(IUnitOfWork unitOfWork)
    {
        this.unitOfWork = unitOfWork;
        DbSet = unitOfWork.DBSet<T, TPrimaryKey>();
    }

    public void Insert(T entity)
    {
        DbSet.Add(entity);
    }

    public IQueryable<T> GetAll()
    {
        return All;
    }

public class BaseRepository<T> : BaseRepository<T, int>, IRepository<T> where T : class
{
    public BaseRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
    {

    }
}

XUnit Test:

    var services = new ServiceCollection();
    services.AddDbContext<TestContext>(a => a.UseInMemoryDatabase("Test"));
    services.AddTransient<DbContext, TestContext>();
    services.AddTransient<IUnitOfWork, UnitOfWork>();
    services.AddTransient(typeof(IRepository<>), typeof(BaseRepository<>));
    ServiceProvider serviceProvider = services.BuildServiceProvider();
    var scope = serviceProvider.CreateScope();

    var testdbContext = scope.ServiceProvider.GetServices<TestContext>();
    var unitOfWork = scope.ServiceProvider.GetService<IUnitOfWork>();

    var ProductRepository = scope.ServiceProvider.GetService<IRepository<Product>>();


    ProductRepository.Insert(new Product {ProductId = 1, ProductName = "ABC";
    ProductRepository.Insert(new Product {ProductId = 2, ProductName = "DEF");
    await unitOfWork.Save();


    public Product()
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public string ProductDescription{ get; set; }
    }

Nothing is saving. During debugging- I Values in DBSet green, but not in all when conducting ProductRepository.GetAll() , doesn't make sense, trying to figure out

在此输入图像描述

Update :

When saving just using DbContext, it works. However, cannot save with Unit of Work.

TestContext.Product.Add(expectedResult[0]);
TestContext.Product.Add(expectedResult[1]);
TestContext.SaveChanges();

Reference question: Net Core: Execute All Dependency Injection in Xunit Test for AppService, Repository, etc

You are registering your services as transient ones, which means DI container creates new instanse each time service is needed to resolve or inject, so the instance of IUnitOfWork that is getting injected into IRepository<> isn't the same you're getting with GetService<IUnitOfWork>() . You can solve it by registering services with services.AddScoped , so that single instance of each service will be created per opened scope.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM