这实际上取决于如何公开您的存储库/数据存储。
不确定“上下文将被关闭,因此我无法执行业务逻辑”是什么意思。在 using 语句内部执行您的业务逻辑。或者,如果您的业务逻辑属于不同的类,那么让我们继续。 :)
有些人从他们的存储库返回具体集合,在这种情况下,您可以将上下文包装在 using 语句中:
public class ArticleRepository
{
public List<Article> GetArticles()
{
List<Article> articles = null;
using (var db = new ArticleNetEntities())
{
articles = db.Articles.Where(something).Take(some).ToList();
}
}
}
这样做的好处是满足连接的良好实践 - 尽可能晚地打开,尽可能早地关闭。
您可以将所有业务逻辑封装在 using 语句中。
缺点 - 您的存储库会意识到我个人不喜欢的业务逻辑,并且您最终会针对每个特定场景使用不同的方法。
第二个选项 - 新建一个上下文作为存储库的一部分,并使其实现 IDisposable。
public class ArticleRepository : IDisposable
{
ArticleNetEntities db;
public ArticleRepository()
{
db = new ArticleNetEntities();
}
public List<Article> GetArticles()
{
List<Article> articles = null;
db.Articles.Where(something).Take(some).ToList();
}
public void Dispose()
{
db.Dispose();
}
}
然后:
using (var repository = new ArticleRepository())
{
var articles = repository.GetArticles();
}
或者第三个选项(我最喜欢的),使用依赖注入。将所有上下文工作与您的 Repository 分离,并让 DI 容器处理资源:
public class ArticleRepository
{
private IObjectContext _ctx;
public ArticleRepository(IObjectContext ctx)
{
_ctx = ctx;
}
public IQueryable<Article> Find()
{
return _ctx.Articles;
}
}
您选择的 DI 容器会将具体的 ObjectContext 注入到 Repository 的实例中,并具有配置的生命周期(Singleton、HttpContext、ThreadLocal 等),并根据该配置进行处理。
我已经设置好了,所以每个 HTTP 请求都会获得一个新的上下文。请求完成后,我的 DI 容器会自动处理上下文。
我在这里也使用了工作单元模式来允许多个存储库使用一个对象上下文。
您可能还注意到我更喜欢从我的存储库中返回 IQueryable(而不是具体的列表)。功能更强大(但如果您不了解其中的含义,则存在风险)。我的服务层在 IQueryable 上执行业务逻辑,然后将具体集合返回给 UI。
这是我迄今为止最强大的选择,因为它允许一个简单的存储库,工作单元管理上下文,服务层管理业务逻辑,DI 容器处理资源/对象的生命周期/处置.
如果您想了解更多信息,请告诉我 - 因为它有很多,甚至比这个令人惊讶的长答案还要多。 :)