【问题标题】:Implementing a generic repository with table-agnostic methods使用与表无关的方法实现通用存储库
【发布时间】:2019-03-05 23:41:42
【问题描述】:

我正在重构持久层以使用真正的通用存储库,并希望最大限度地减少在不同表上执行的类似查询的数量 - 想想像从表 a、b 或 c 中获取 id 之类的事情,其中查询仅因表而异。

到目前为止,我的存储库如下所示:

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

public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    /// ctor stuff omitted ...

    public void Insert(TEntity entity)
    {
        _db.Insert<TEntity>(entity);
    }

    public void Update(TEntity entity)
    {
        _db.Update<TEntity>(entity);
    }
}

public interface IDerivedRepository : IRepository<MyEntity>
{
    // defines interface methods not found on the base IRepository
}

public class DerivedRepository : BaseRepository<MyEntity>, IDerivedRepository
{
    // implements methods defined on IDerivedRepository, and inherits Insert and Update from BaseRepository
}

这很好用,因为任何新的存储库都可以继承基础存储库上定义的方法,这些方法与类型无关,因为我可以简单地发送一个实体,我的 ORM (NPoco) 管理插入/更新。

我想扩展它以允许简单的 get/fetch 类型方法的通用基本定义 - 通过 id 或简单计数获取是明显的例子。目前,我在适当的存储库中实现这些,因此最终会使用多个存储库方法(在不同的存储库中)调用本质上相同的代码。

下面的示例已简化(_db 管理范围等),但突出显示了我要避免的 - 表和返回类型不同的重复 GetById 方法

public class DerivedRepositoryA : BaseRepository<A>, IDerivedARepository
{
    public A GetById(int id) {
        return _db.Fetch<A>("select * from TableA where id = @0", id);
    }
}

public class DerivedRepositoryB : BaseRepository<B>, IDerivedBRepository
{
    public B GetById(int id) {
        return _db.Fetch<B>("select * from TableB where id = @0", id);
    }
}

public class DerivedRepositoryC : BaseRepository<C>, IDerivedCRepository
{
    public C GetById(int id) {
        return _db.Fetch<C>("select * from TableC where id = @0", id);
    }
}

有可能吗,我该怎么做?

【问题讨论】:

  • 你说“目前,我在适当的存储库中实现了这些,所以最终有多个存储库方法” - 所以请给我们看这段代码。
  • 当然 - 已更新问题
  • 这只是想到的一种方式...您可以在 TEntity 中定义 2 个属性,例如 TableName 和 Parameter 并使用字符串插值 select * from {entity.TableName} where {entity.Paramater } = 等等...

标签: c# npoco


【解决方案1】:

下面的BaseRepository&lt;TEntity&gt; 实现默认使用类型名作为表名,但如果需要,允许使用与类型名不同的自定义表名。

public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private readonly string tableName;

    public BaseRepository() : this(typeof(TEntity).Name)
    {

    }

    public BaseRepository(string tableName)
    {
        this.tableName = tableName;
    }

    public TEntity GetById(int id)
    {
        return _db.Fetch<TEntity>($"select * from Table{tableName} where id = {id}");
    }
}

【讨论】:

  • 这与我最终所做的非常相似 - 我的 pocos 装饰有 NPoco 属性,因此我可以(例如)通过一些反射魔法获取表名并在sql字符串。似乎正在做这项工作。
【解决方案2】:

你不需要表名,这样就可以了

    return _db.Single<TEntity>("where id = @id", id);  //Or Fetch

你可以做这样的事情,让 NPoco 处理 SQL。您也可以将其用于 Save() 或 Delete () 也

    public T GetByID<T>(Int32 ID)
    {
        try
        {
            if (ID == 0)
                throw (new ArgumentNullException("ID cannot be 0"));

            return _db.SingleOrDefaultById<T>(ID);
        }
        catch { throw; }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    • 2019-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多