如何在 .NET 中实现正确的存储库模式

How to implement a correct repository pattern in .NET

article 解释了如何创建具有所有基本 CRUD 操作的通用 HttpClient class。然后它为特定的 POCO 对象(称为成员)创建一个特定类型的存储库。

我不明白的是 MemberReposity class 的需求,即 return GenericHttpClient class 对特定类型 return 的确切需求?我不能简单地将 GenericHttpClient 重命名为 GenericReposity,然后将它用于我所有的 POCO 对象 CRUD 操作吗?换句话说,如果每个对象都只需要基本的 CRUD 操作,为什么我需要为每个对象创建一个唯一的存储库?

我可以像这样在我的表单上简单地实例化它们:

private GenericReposity<Customer, int> _customerClient = new GenericReposity<Customer, string>(url, "api/Customers/");

然后通过这种方式获得客户:

_customerClient.GetAsync(5);

我是不是漏掉了一点?


更新

阅读反模式后,我设计了一个基本存储库界面如下:

internal interface IGenericRepository<T, in TResourceIdentifier>
{
    Task<IEnumerable<T>> GetManyAsync();
    Task<T> GetAsync(TResourceIdentifier id);
    Task PutAsync(T model);
    Task<T> PostAsync(T model);
    Task DeleteAsync(TResourceIdentifier id);
}

然后我实现了:

public class GenericRepository<T, TResourceIdentifier> : IDisposable, IGenericRepository<T, TResourceIdentifier> 
    where T : class
{
    private bool _disposed;
    protected HttpClientHelper<T, TResourceIdentifier> Client;

    protected GenericRepository(string addressSuffix)
    {
        Client = new HttpClientHelper<T, TResourceIdentifier>(Properties.Settings.Url, addressSuffix);
    }

    public async Task<IEnumerable<T>> GetManyAsync()
    {
        return await Client.GetManyAsync();
    }

    // All other CRUD methods and dispose
}

然后我为我的每个实体创建了自定义存储库界面。例如:

internal interface IOrderRepository : IGenericRepository<Order, int>
{
    Task<IEnumerable<Order>> GetOrderBySomeConditionAsync(string condition );

}

最后,我实现了自定义存储库:

public class OrderRepository : GenericRepository<Order, int>, IOrderRepository
{
    public OrderRepository(string addressSuffix) : base(addressSuffix)
    {
    }

    public async Task<IEnumerable<Order>> GetOrderBySomeConditionAsync(string condition)
    {
        //get all the orders (GetManyAsync()) and then returns the ones meeting the condition
    }
}

这样我就可以获得所有简单的 CRUD 操作,而不必为每个实体以及任何自定义实体一一实施它们。 这是正确的方法吗?或者这被认为是反模式?

有一天您可能想要添加每个实体类型唯一的东西,例如数据验证,或者在数据处于静止状态时加密个人信息。

您的新方法(更新后)看起来很棒。

有了这个,你就绕过了通用存储库的所有缺点;仍在利用基本通用存储库中的代码重用。

没什么大不了的,但考虑在基础存储库中制作所有方法 protected 以便这些方法只能在具体存储库中访问。当然,如果所有具体存储库都实现了该方法,则可以忽略此建议。