【问题标题】:Use Repository factory and repository factor design pattern together一起使用存储库工厂和存储库因子设计模式
【发布时间】:2020-11-25 20:03:54
【问题描述】:

我的 DbRepository 类如下:

public class DbRepository<TEntity, TDbContext> : IRepository<TEntity>
    where TEntity : class, IEntity
    where TDbContext : DbContext
{
    protected readonly TDbContext dbContext;

    /// <summary>
    ///     Initializes a new instance of the <see cref="DbRepository{TEntity}" /> class.
    /// </summary>
    public DbRepository(TDbContext dbContext)
    {
        this.dbContext = dbContext;
    }

    /// <inheritdoc/>
    public async Task<TEntity> AddAsync(TEntity entity)
    {
        ObjectCheck.EntityCheck(entity, $"{nameof(TEntity)} missing.");
        await dbContext.Set<TEntity>().AddAsync(entity);
        await dbContext.SaveChangesAsync();
        return entity;
    }

    /// <inheritdoc/>
    public virtual async Task<TEntity> GetAsync(object primaryKey)
    {
        ObjectCheck.PrimaryKeyCheck(primaryKey, $"primaryKey <= 0 in {nameof(IRepository<TEntity>)}");
        return await dbContext.Set<TEntity>().FindAsync(primaryKey);
    }

    /// <inheritdoc/>
    public virtual IQueryable<TEntity> GetAll(Expression<Func<TEntity, bool>> filter = null)
    {
        return (filter != null ? dbContext.Set<TEntity>().Where(filter) : dbContext.Set<TEntity>());
    }

    /// <inheritdoc/>
    public virtual async Task<TEntity> GetSingleAsync(Expression<Func<TEntity, bool>> filter)
    {
        return await dbContext.Set<TEntity>().SingleOrDefaultAsync(filter);
    }

    /// <inheritdoc/>
    public virtual async Task<TEntity> UpdateAsync(TEntity entity)
    {
        ObjectCheck.EntityCheck(entity, $"{nameof(TEntity)} missing.");
        dbContext.Set<TEntity>().Update(entity);
        await dbContext.SaveChangesAsync();
        return entity;
    }

    /// <inheritdoc/>
    public virtual async Task DeleteAsync(object primaryKey)
    {
        var entityToBeDeleted = await GetAsync(primaryKey);
        ObjectCheck.EntityCheck(entityToBeDeleted, $"{nameof(TEntity)} missing.");

        dbContext.Set<TEntity>().Remove(entityToBeDeleted);
        await dbContext.SaveChangesAsync();
    }

}

我的界面如下:

   public interface IRepository<TEntity>
      where TEntity : class, IEntity
   {
    Task<TEntity> GetAsync(object primaryKey);

    IQueryable<TEntity> GetAll(Expression<Func<TEntity, bool>> filter = null);

    Task<TEntity> GetSingleAsync(Expression<Func<TEntity, bool>> filter);

    Task<TEntity> AddAsync(TEntity entity);

    Task<TEntity> UpdateAsync(TEntity entity);

    Task DeleteAsync(object primaryKey);
   }
    

如何在启动时将它们注册为作用域并告诉每个类创建存储库?那么我可以在这些存储库上编写测试吗?

我有 4 个模型,我不想为每个模型创建存储库类和接口它们总是相同的 - 简单的 crud 操作。相反,我希望工厂创建它们。

public class RepositoryFactory
    {
        public static TRepository GetRepositoryInstance<T, TRepository>()
         where TRepository : IRepository<T>, new()
        {
            return new TRepository();
        }
    }

我得到的错误是类型必须是引用类型才能在泛型类型或方法 IRepository 中用作参数 TEntity

【问题讨论】:

  • DI 用于创建您的实例。当你想用工厂创建时,你最好注册工厂。在您的情况下,我将通过将静态方法转换为实例方法并在启动时在 DI 中注册 RepositoryFactory: services.AddSingleton(new RepositoryFactory());单例,因为工厂模式是创建模式,您使用工厂来创建您的存储库,而不是 DI。另一种注册方法是将工厂放在一边并这样做: services.AddScoped, Repository();并为所有 4 个实体执行此操作。总而言之,我不推荐任何这些解决方案

标签: c# generics repository factory


【解决方案1】:

它给你这个错误是因为在 IRepository 接口中你告诉 T 必须是一个类(引用类型)并且它必须实现 IEntity 接口。

在工厂里,你一个都没说。

可能你必须写这样的东西:

public class RepositoryFactory
{
    public static TRepository GetRepositoryInstance<T, TRepository>()
          where TRepository : IRepository<T>, new()
          where T : class, IEntity
    {
        return new TRepository();
    }
}

【讨论】:

  • 谢谢。我是否将此通用存储库注册为作用域以及如何在 Startup 中执行此操作?我通常会做类似 services.AddScoped();在这种情况下我该怎么办?
猜你喜欢
  • 2016-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多