【问题标题】:Using Method of Inherited Interface with Generic Repository Pattern, UnitOfWork in ASP.NET MVC 5在 ASP.NET MVC 5 中使用具有通用存储库模式、UnitOfWork 的继承接口的方法
【发布时间】:2017-04-19 20:28:56
【问题描述】:

我的问题来自这里,


我已经为国家存储库编写了一个接口,并且我正在使用 UnitOfWork 跟踪通用存储库,我还使用 ninject 进行 DI

public interface ICountryRepository : IRepository<Country>
{
    List<Country> GetAll();
}

实施国家资料库接口,

public class CountryRepository : BaseRepository<Country>, ICountryRepository
{
    public CountryRepository(DbContextcontext) : base(context)
    {
    }

    public List<Country> GetAll(){
    // Not implemented
    }
} 

ICountryRepository 接口中还有一个额外的方法,我也实现了。但是当我需要使用 UnitOfWork 使用该方法时,我不能使用该方法。那是给 System.NullReferenceException

我试过了,

ICountryRepository repository = UnitOfWork.Repository<Country>() as ICountryRepository;
return repository.GetAll();

向下转换建议该方法,但没有转换该方法是不可访问

给出了附加代码,

实体


基础实体

    public class BaseEntity
    {
        public int Id { get; set; }
    }

产品实体

public class Country : BaseEntity
{
    public string Name { get; set; }
}

存储库


界面

public interface IRepository<T>
{
    void Add(T entity);
}

基础存储库

public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : BaseEntity
{
    protected IDbContext _context;
    private readonly IDbSet<TEntity> _dbEntitySet;
    private bool _disposed;

    public BaseRepository(IDbContext context)
    {
        _context = context;
        _dbEntitySet = _context.Set<TEntity>();
    }

    public void Add(TEntity entity)
    {
        _context.SetAsAdded(entity);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public virtual void Dispose(bool disposing)
    {
        if (!_disposed && disposing)
        {
            _context.Dispose();
        }
        _disposed = true;
    }
}

工作单元


界面

public interface IUnitOfWork : IDisposable
{
    IRepository<TEntity> Repository<TEntity>() where TEntity : BaseEntity;

    void BeginTransaction();

    int Commit();

    Task<int> CommitAsync();

    void Rollback();

    void Dispose(bool disposing);

}

实施的工作单元

public class UnitOfWork : IUnitOfWork
{
    private readonly IDbContext _context;
    private bool _disposed;
    private Hashtable _repositories;

    public UnitOfWork(IDbContext context)
    {
        _context = context;
    }

    public IRepository<TEntity> Repository<TEntity>() where TEntity : BaseEntity
    {
        if (_repositories == null)
        {
            _repositories = new Hashtable();
        }

        var type = typeof(TEntity).Name;

        if (_repositories.ContainsKey(type))
        {
            return (IRepository<TEntity>)_repositories[type];
        }

        var repositoryType = typeof(BaseRepository<>);

        _repositories.Add(type, Activator.CreateInstance(repositoryType.MakeGenericType(typeof(TEntity)), _context));

        return (IRepository<TEntity>)_repositories[type];
    }

   /* Other Implementation
    *
    *
    *
    */
}

【问题讨论】:

  • 可能在这一行:_context.Set&lt;TEntity&gt;()。您正在传递BaseProduct,它不是一个实体,然后EF 无法创建DBSetUnitOfWork.Repository&lt;Country&gt; 应该可以,但 UnitOfWork.Repository&lt;BaseProduct&gt; 不行。
  • 我已经编辑过了,不幸的是这不是问题所在。我仍然面临@smoksnes 的问题
  • 似乎没有实现IBaseProductRepository,因此您的演员阵容将始终为空。另外,使用Activator 有什么特别的原因吗?没有什么魔法发生。你应该可以使用new BaseRepository&lt;TEntity&gt;(_context)
  • @smoksnes,我改变了这个错误。我正在使用 Ninject 进行依赖注入,它正在发挥作用。但是问题还是没有解决。

标签: c# asp.net-mvc entity-framework repository-pattern unit-of-work


【解决方案1】:

正如评论中所说,您正在解析BaseRepository&lt;Country&gt; 类型的实例,而不是您的派生CountryRepository 类,这是您在Country 的情况下要解析的类。

一种粗略的硬编码解决方案是将您的 generic-repository-type-to-resolve 替换为 custom-type-to-resolve。像这样的东西。您需要手动将条目添加到字典中。

private static readonly Dictionary<Type, Type> s_RepositorySuperTypes = new Dictionary<Type, Type> {
    { typeof(BaseRepository<Country>), typeof(CountryRepository) }
};

public IRepository<TEntity> Repository<TEntity>() where TEntity : BaseEntity {
    if (_repositories == null) {
        _repositories = new Hashtable();
    }

    var type = typeof(TEntity).Name;
    if (_repositories.ContainsKey(type)) {
        return (IRepository<TEntity>)_repositories[type];
    }

    var closedRepositoryType = typeof(BaseRepository<>).MakeGenericType(typeof(TEntity));
    if (s_RepositorySuperTypes.ContainsKey(closedRepositoryType)) {
        closedRepositoryType = s_RepositorySuperTypes[closedRepositoryType];
    }
    _repositories.Add(type, Activator.CreateInstance(closedRepositoryType, _context));

    return (IRepository<TEntity>)_repositories[type];
}

【讨论】:

    【解决方案2】:

    您应该使您的自定义存储库方法扩展方法。

    所以如果你的额外方法被称为 GetCountriesByContinent 类似

    public static class CountryRepository
    {
        public static IEnumberable<Country> GetCountriesByContinent(this IRepository<Country> repo, string continent)
        {
            return repo.Where(c => c.Continent == continent);
        }
    }
    

    您还应该研究协变与逆变,这可能会帮助您了解为什么会首先出现此问题。

    【讨论】:

      猜你喜欢
      • 2016-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      • 1970-01-01
      • 2011-04-19
      • 1970-01-01
      相关资源
      最近更新 更多