1. 每个查询之后我应该关闭连接吗?
.Net会自动处理这个问题,这是垃圾回收器的任务。所以不必手动释放对象,Jon Skeet提供了一个很好的答案:https://dev59.com/c3I-5IYBdhLWcg3wJEwK#1998600。但你可以使用using(IDisposable){ }
语句来强制垃圾回收器起作用。这里有一篇关于资源重分配的好文章:http://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About。
2. 静态类中的连接是否好?
永远不要将数据上下文设置为静态!数据上下文既不是线程安全的,也不是并发安全的。
3. 是否有适用于此问题的良好设计模式?
如Belogix所说,依赖注入和工作单元模式非常好,事实上实体框架本身就是一个工作单元。虽然DI和UoW有点被高估了,如果这是你第一次处理IoC容器,那么它并不容易实现。如果要选择这条道路,我建议使用Ninject。另外,如果您不打算运行测试,您实际上并不需要DI。这些模式的强大之处在于解耦,这样您就可以轻松进行测试和模拟。
简而言之:如果您要对代码进行测试,请使用这些模式。如果没有,我将向您提供一个关于如何在所需的服务之间共享数据上下文的示例。这是您第四个问题的答案。
4. 建立数据库连接的最佳方法是什么(静态的,每个请求的)?
您的上下文服务:
public class FooContextService {
private readonly FooContext _ctx;
public FooContext Context { get { return _ctx; } }
public FooContextService() {
_ctx = new FooContext();
}
}
其他服务:
public class UnicornService {
private readonly FooContext _ctx;
public UnicornService(FooContextService contextService) {
if (contextService == null)
throw new ArgumentNullException("contextService");
_ctx = contextService.Context;
}
public ICollection<Unicorn> GetList() {
return _ctx.Unicorns.ToList();
}
}
public class DragonService {
private readonly FooContext _ctx;
public DragonService(FooContextService contextService) {
if (contextService == null)
throw new ArgumentNullException("contextService");
_ctx = contextService.Context;
}
public ICollection<Dragon> GetList() {
return _ctx.Dragons.ToList();
}
}
Controller:
public class FantasyController : Controller {
private readonly FooContextService _contextService = new FooContextService();
private readonly UnicornService _unicornService;
private readonly DragonService _dragonService;
public FantasyController() {
_unicornService = new UnicornService(_contextService);
_dragonService = new DragonService(_contextService);
}
}
重新考虑一下(几乎是编辑):
如果您需要上下文不为实体创建代理,因此也没有延迟加载,您可以按以下方式重载上下文服务:
public class FooContextService {
private readonly FooContext _ctx;
public FooContext Context { get { return _ctx; } }
public FooContextService() : this(true) { }
public FooContextService(bool proxyCreationEnabled) {
_ctx = new FooContext();
_ctx.Configuration.ProxyCreationEnabled = proxyCreationEnabled;
}
}
注意:
- 如果将代理创建启用设置为false,您将无法开箱即用地进行延迟加载。
- 如果您有API控制器,则不希望处理任何完整的对象图。
编辑:
首先阅读一些内容:
完成这个:
(_context as IObjectContextAdapter).ObjectContext.Connection.Open()
这是一篇关于管理连接和事务的优秀文章。
实体框架通过 Connection 属性公开 EntityConnection。阅读为:public sealed class EntityConnection : DbConnection
。
管理连接时需要考虑以下事项:(来自上述链接)
- 如果对象上下文在操作之前未打开连接,则会打开该连接。如果对象上下文在操作期间打开了连接,则始终会在操作完成时关闭该连接。
- 如果您手动打开连接,则对象上下文不会关闭它。调用 Close 或 Dispose 将关闭连接。
- 如果对象上下文创建连接,则在上下文被处置时始终会处理该连接。
- 在长时间运行的对象上下文中,必须确保在不再需要时处置上下文。
希望对您有所帮助。