Реализация репозитория Generi c с базовым репозиторием как абстрактный класс - PullRequest
0 голосов
/ 01 августа 2020

net основной проект. Я пытаюсь реализовать общий шаблон репозитория c. У меня есть базовый репозиторий, который является абстрактным. Поэтому я переопределяю базовый репозиторий и создаю другие свои репозитории. Реализация выглядит ниже.

BaseRepository.cs

 public abstract class BaseRepository<T>: IBaseRepository<T>
        where T : class
    {
       private readonly DbContext dbContext;
       private readonly DbSet<T> dbSet;
       public BaseRepository(DbContext dbContext)
        {
            this.dbContext = dbContext;
            this.dbSet = dbContext?.Set<T>();
        }
      public async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, params Expression<Func<T, object>>[] includes)
        {
            IQueryable<T> query = this.dbSet;
            foreach (Expression<Func<T, object>> include in includes)
            {
                query = query.Include(include);
            }

            if (filter != null)
            {
                query = query.Where(filter);
            }

            if (orderBy != null)
            {
                query = orderBy(query);
            }

            return await query.ToListAsync().ConfigureAwait(false);
        }
     }
   }

Repository.cs

public class Repository<T> : BaseRepository<T>, IRepository<T>
        where T : class
    {
     private readonly DbContext dbContext;
     private readonly DbSet<T> dbSet;
     public Repository(DbContext context) : base(context)
        {
        }
     public async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, params Expression<Func<T, object>>[] includes)
        {
            IQueryable<T> query = this.dbSet;
            foreach (Expression<Func<T, object>> include in includes)
            {
                query = query.Include(include);
            }

            if (filter != null)
            {
                query = query.Where(filter);
            }

            if (orderBy != null)
            {
                query = orderBy(query);
            }

            return await query.ToListAsync().ConfigureAwait(false);
        }
     }
   }

UnitOfWork.cs

public class UnitOfWork<TContext> : IUnitOfWork<TContext>
        where TContext : DbContext, IDisposable
    {
     private readonly MyContext context;
     private Dictionary<(Type type, string name), object> _repositories;
     public UnitOfWork(MyContext myContext)
        {
            if (this.context == null)
            {
                this.context = myContext;
            }
        }
     public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
        {
            return (IRepository<TEntity>)GetOrAddRepository(typeof(TEntity), new Repository<TEntity>(Context));
        }
      public async Task<int> CompleteAsync()
        {
            try
            {
                return await this.context.SaveChangesAsync().ConfigureAwait(false);
            }
            catch (DbUpdateConcurrencyException ex)
            {
                ex.Entries.Single().Reload();
                return await this.context.SaveChangesAsync().ConfigureAwait(false);
            }
        }
      internal object GetOrAddRepository(Type type, object repo)
        {
            _repositories ??= new Dictionary<(Type type, string Name), object>();

            if (_repositories.TryGetValue((type, repo.GetType().FullName), out var repository)) return repository;
            _repositories.Add((type, repo.GetType().FullName), repo);
            return repo;
        }
    }
  }

Then In my Файл startup.cs, когда я регистрирую

services.AddDbContext<MyContext>(options =>
       options.UseSqlServer(this.Configuration["AzureSQLConnectionString"]));
        services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
        services.AddScoped<IUnitOfWork, UnitOfWork>();

UnitofWork выдает мне ошибку, используя общий c тип. «UnitofWork» требует 1 тип аргумента. Потом добавил services.AddScoped<IUnitOfWork, UnitOfWork<MyContext>>(). Теперь его ошибка выброса в методе GetAsyn c в Repository.cs. Ошибка: Параметр: требуется источник, он не может быть пустым. Затем я обнаружил

IQueryable query = this.dbSet;

запрос пуст. Итак, я понял, что у меня проблемы с установкой соединения с db. Может ли кто-нибудь помочь мне, что именно я здесь делаю не так? Любая помощь будет принята с благодарностью. Спасибо

1 Ответ

0 голосов
/ 01 августа 2020

Измените эти классы следующим образом:

public abstract class BaseRepository<T>: IBaseRepository<T>
        where T : class
    {
       protected readonly DbContext dbContext;
       protected readonly DbSet<T> dbSet;

       public BaseRepository(DbContext dbContext)
        {
            this.dbContext = dbContext;
            this.dbSet = dbContext?.Set<T>();
        }
      public virtual async Task<IEnumerable<T>> GetAsync(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, params Expression<Func<T, object>>[] includes)
        {
            IQueryable<T> query = this.dbSet;
            foreach (Expression<Func<T, object>> include in includes)
            {
                query = query.Include(include);
            }

            if (filter != null)
            {
                query = query.Where(filter);
            }

            if (orderBy != null)
            {
                query = orderBy(query);
            }

            return await query.ToListAsync().ConfigureAwait(false);
        }
     }

public class Repository<T> : BaseRepository<T>, IRepository<T>
        where T : class
    {
     
        public Repository(DbContext context) : base(context)
        {
        }

        //override GetAsync if different than base. In your case it is not.
     }
...