我想知道在这种情况下我的下面的实现是否是处理SQL连接的最有效方法。
我通常知道如果我直接使用SqlConnection,我可以将连接包装在using块中以自动处理它,但在这种情况下,我想保持连接打开并可用于SQLRespository类中的所有方法
public class SqlRepository : IRepository
{
private readonly string connectionString;
private SqlConnection connection;
public SqlRepository(string connectionString)
{
this.connectionString = connectionString;
connection = new SqlConnection(connectionString);
connection.Open();
}
public void Method_A()
{
// uses the SqlConnection to fetch data
}
public void Method_B()
{
// uses the SqlConnection to fetch data
}
public void Dispose()
{
connection.Dispose();
}
}
用法:
using (IRepository repository = new SqlRepository(connectionString))
{
var item = repository.items;
}
更新 IRepository确实实现了IDisposable
答案 0 :(得分:10)
不要保持连接打开跨越呼叫。你正在打败连接池。
如果您正在使用汇集的连接(如sqlserver),它将进行池化和重用。只需在a&方法中打开和关闭湾
你可以争辩说,如果调用者做了你用一个方法调用它所做的事情就没问题了。但是如果你在每个工作方法(1)中使用带有sqlconnection的{},代码将更简单,并且(2)你确保池不会被破坏(意味着当其他请求可以使用它时,你可以将池中的项目排除在池外)
编辑:
根据评论添加伪。
模式有问题,因为调用者可以这样做。
//pseudo code
using (SqlRepository r)
{
r.MethodA();
// other code here that takes some time. your holding a connection
// out of the pool and being selfish. other threads could have
// used your connection before you get a chance to use it again.
r.MethodB();
} // freed for others here.
这会破坏服务器的可扩展性 - 相信我。我已经看到非常大的系统被这种窒息 - 通常是因为它们正在跨越AT侧交易。
更好的模式:
class Repository
{
void MethodA()
{
using (Sqlconnection)
{
// db call
}
}
void MethodB()
{
using (Sqlconnection)
{
// you can even have multiple calls here (roundtrips)
// and start transactions. although that can be problematic
// for other reasons.
}
}
现在,游泳池最有效。我意识到问题在于一次性模式 - 是的,你可以做到。但是......
我不会让连接跨越存储库的生命周期。
答案 1 :(得分:2)
如果您想这样做,请确保实现IDisposable(我无法告诉您是否在IRepository界面上注明了这一点)并且我会做类似的事情:
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
显然这里的_context是你的SqlConnection。
但是 - 您确定每个存储库需要一个连接吗?那些跨越多个存储库的操作呢?
答案 2 :(得分:1)
假设IRepository
继承自IDisposable
,您的实现很好,前提是您没有让SqlRepository
类的实例打开的时间超过执行“逻辑”序列所需的时间。查询数据库。此序列可能跨越多个方法调用的事实不是问题。
我不同意@ bryanmac的回答:
不要保持连接打开跨越呼叫。你正在打败连接池。
如果您的方法调用序列属于一起,并且您没有保持连接打开的时间超过完成逻辑序列所需的时间,我不会看到这会以任何方式阻止连接池。
虽然有一条评论。你应该:
实现标准IDisposable
模式(使用可在派生类中重写的protected void Dispose(bool disposing)
方法
或者让您的课程密封,在这种情况下,您现有的IDisposable
实施工作正常。