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

时间:2018-10-12 20:37:25

标签: .net repository-pattern crud

article说明了如何使用所有基本的CRUD操作创建通用的HttpClient类。然后,它为特定的POCO对象(称为成员)创建类型特定的存储库。

我无法理解的是,对于MemberReposity类的需求是否恰好返回了GenericHttpClient类针对特定类型返回的内容?我不能简单地将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操作,而不必为每个实体以及任何自定义对象一一实现。 这是正确的方法吗?还是这被认为是反模式?

2 个答案:

答案 0 :(得分:1)

总有一天,您可能希望添加每种实体类型唯一的内容,例如数据验证,或者在数据静止时加密个人信息。

答案 1 :(得分:1)

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

由此,您可以绕过通用存储库的所有缺点;仍然利用基础通用存储库中的代码重用。

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