我已经使用存储库模式创建了数据提供程序。
首先,我设计了一个基本的存储库接口,如下所示:
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
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(_disposed || !disposing) return;
if(Client != null)
{
var mc = Client;
Client = null;
mc.Dispose();
}
_disposed = true;
}
}
然后,我为每个实体创建了自定义存储库界面。例如:
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
}
}
请注意,HttpClientHelper
使用HttpClient
,需要手动处理。
我已经创建了MVC Web应用程序,并在类级别定义了存储库,如下所示:
IOrderRepository _orderRepository = new OrderRepository();
当我在CRUD操作中调用_orderRepository
时,它在使用后不会碰到处置。为了解决这个问题,我最终实现了这样的方法:
private async Task<IEnumerable<OrderViewModel>> GetOrders()
{
using(var orderRepository = new OrderRepository())
return await orderRepository.GetManyAsync();
}
这将达到Dispose,但是是反模式。
在实现过程中我遗漏了哪些实例没有在每次调用中都被处置?
答案 0 :(得分:3)
您不应在每次请求后都丢弃HTTPClient。
如上面的链接所述-
因此,HttpClient旨在实例化一次并重新使用 在应用程序的整个生命周期中。实例化HttpClient 每个请求的类将耗尽可用的套接字数量 在重负载下。该问题将导致SocketException错误。 解决该问题的可能方法基于创建 HttpClient对象是单例还是静态,如本节所述 Microsoft关于HttpClient使用情况的文章。
答案 1 :(得分:1)
在通用存储库中编写Dispose方法并不意味着将在需要时自动调用它。它打算单独调用,因此,为什么您必须要么使用using
语句(如您所示),要么在代码内使用Dispose
方法。
或者,您可以将该工作留给垃圾收集器。
如果您确信使用GC.SuppressFinalize(this);
在此处详细了解-When should I use GC.SuppressFinalize()?
正如R Jain所指出的,您还应该创建一个静态类来保存HttpClient。您必须根据需要使用HttpResponseMessages或HttpContent。
更多资源可供阅读: