可以将Datacontext设置为存储库中的属性吗?
-
03-07-2019 - |
题
将datacontext设置为属性是否存在任何潜在问题:
存储库
public Repository()
{
public DataContext dc {get;set;}
public GetOrders(int id)
{ ...from dc.Orders...}
}
服务层:
public GetNewOrders()
{
....
Repository rep=new Repository();
using {DataContext dc=new DataContext())
{
rep.dc=dc;
rep.GetOrders(id);
}
}
解决方案
在DDD中,你通过引用concret类错过了这里的大局。您没有在存储库和“服务层”之间进行接口连接。通过最佳实践。如果必须将DataContext注入到存储库中,我建议重构为:
public interface IRepository
{
IList<Orders> GetNewOrders();
}
public Repository : IRepository
{
private IDataContext _dataContext;
public Repository(IDataContext dataContext)
{
_dataContext = dataContext;
}
public IList<Orders> GetNewOrders()
{
// perform your actions on _dataContext here
}
}
更好的解决方案是让Repository自己处理DataContext - 通过屏蔽底层需求来保持Concert的分离:
public interface IRepository
{
IList<Orders> GetNewOrders();
}
public Repository : IRepository
{
private IDataContext _dataContext;
public Repository(String connectionString)
{
_dataContext = new DataContext(connectionString);
}
public IList<Orders> GetNewOrders()
{
// perform your actions on _dataContext here
}
}
如果您必须自己保持对DataContext(或其他类)的控制(可能您希望保留静态引用,或者更改基于WebRequest的设置等),您将需要使用“工厂”和“工厂”。
工厂看起来像这样:
public static class DataContextFactory
{
public static IDataContext GetInstance()
{
// return either a static instance,
// or threaded instance, a GlobalContext instance
// or whatever your preference is here
//
}
}
这样,您可以完全控制DataContext实例如何在外部和远离“服务”控制的情况下进行控制。层。因此,您将使用此DataContextFactory,如下所示:
public interface IRepository
{
IList<Orders> GetNewOrders();
}
public Repository : IRepository
{
public IList<Orders> GetNewOrders()
{
using (var dataContext = DataContextFactory.GetInstance())
{
// dataContext is now your IDataContext to work with
}
}
}
“如何访问IRepository?”你可能会问?
您的服务层可以执行以下操作:
public void GetNewOrdersForServices()
{
// Not recommended!
// IRepository repo = new Repository()
//
// The following is recommended instead; because, it removes the
// the Concret reference from your Services layer completely!
//
IRepository repo = ServiceLocator.InstanceOf<IRepository>();
IList myList = repo.GetNewOrders();
}
或者,您可以使用您最喜欢的Inversion of Control容器将其注入服务的构造函数中,如下所示:
public class OrderService
{
private IRepository _repo;
public OrderService(IRepository repo)
{
_repo = repo;
}
public void GetNewOrdersForServices()
{
IList myList = _repo.GetNewOrders();
}
如果您与服务定位器概念不相似,请查看Castle Windsor,因为它封装了您的所有需求。
其他提示
根据我的阅读,使用DataContext“对于多个商务对话,通常是错误的做法 。向下滚动到为什么这么重要?部分的报价。由于缓存和其他因素,您应该立即考虑您的DataContext陈旧。由此可以肯定地说,您不希望将DataContext保留为所有方法都重用的属性。使用Eric Duncan的建议,您将需要传递某种DataContext工厂来为每个查询获取新的上下文。
对于专注于DataContext的讨论,APress Pro LINQ 一书有整章,非常最后一页还建议您“立即考虑DataContext陈旧”。