C# Oracle DataReader正在关闭连接,然后才能读取数据
我有一个返回C# Oracle DataReader正在关闭连接,然后才能读取数据,c#,oracle,wcf,C#,Oracle,Wcf,我有一个返回OracleDataReader对象的函数。这是: public OracleDataReader executeCommand(string query) { using (conn) { conn.ConnectionString = connectionString; conn.Open(); OracleCommand cmd = conn.CreateComma
OracleDataReader
对象的函数。这是:
public OracleDataReader executeCommand(string query)
{
using (conn)
{
conn.ConnectionString = connectionString;
conn.Open();
OracleCommand cmd = conn.CreateCommand();
cmd.CommandText = query;
OracleDataReader reader = cmd.ExecuteReader();
return reader;
}
}
当我试图通过另一个类中的reader获取数据时,我遇到了一个异常:
public Person GetPersonById(int id)
{
OracleDBOp db = new OracleDBOp();
String query = "select * from test_person where id=" + id;
OracleDataReader reader = db.executeCommand(query);
Person person = null;
person = new Person(Convert.ToInt32(reader["id"]),reader["first_name"].ToString(),reader["last_name"].ToString());
return person;
}
异常当读卡器关闭时,获取序号的尝试无效
有什么问题?我没有关闭读卡器?您的代码会在退出
using
作用域后立即关闭连接,因此任何读取尝试都将失败:
using (conn)
{
conn.ConnectionString = connectionString;
conn.Open();
...
return reader;
} --> Disposes of connection, which closes it, so reader can't read.
一个选项是使用块将连接放置在中,而不是将连接放置在块中,如果要将读取器
传递到拥有连接的方法的控制之外,可以指定CommandBehavior.CloseConnection
在读取器关闭时关闭连接,但不要关闭或处理连接,即
OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return reader;
在我看来,一种更安全的模式(如果您使用foreach
),而不将资源处置的责任留给调用者,也不将读取器传递到函数之外,将使用产生返回
,尽管这将改变代码的工作方式:
public IEnumerable<Person> RetrievePeople()
{
using (var conn = new OracleConnection(connString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
yield return new new Person(
Convert.ToInt32(reader["id"]),
reader["first_name"].ToString(),
reader["last_name"].ToString());
}
}
}
}
}
public IEnumerable RetrievePeople()
{
使用(var conn=新的OracleConnection(connString))
{
conn.Open();
使用(var cmd=conn.CreateCommand())
{
cmd.CommandText=查询;
使用(var reader=cmd.ExecuteReader())
{
while(reader.Read())
{
回报新人(
转换.ToInt32(读卡器[“id”]),
读取器[“first_name”]。ToString(),
读卡器[“姓氏].ToString());
}
}
}
}
}
通过这种方式,您不需要传递读取器,但是,在迭代器完成之前,连接将保持打开状态。这样做的好处是保留了读卡器的惰性评估方法,而无需实际传递读卡器,也无需问之后谁将清理连接。一旦退出using
作用域,您的代码就会关闭连接,因此,任何读取尝试都将失败:
using (conn)
{
conn.ConnectionString = connectionString;
conn.Open();
...
return reader;
} --> Disposes of connection, which closes it, so reader can't read.
一个选项是使用
块将连接放置在中,而不是将连接放置在块中,如果要将读取器
传递到拥有连接的方法的控制之外,可以指定CommandBehavior.CloseConnection
在读取器关闭时关闭连接,但不要关闭或处理连接,即
OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return reader;
在我看来,一种更安全的模式(如果您使用foreach
),而不将资源处置的责任留给调用者,也不将读取器传递到函数之外,将使用产生返回
,尽管这将改变代码的工作方式:
public IEnumerable<Person> RetrievePeople()
{
using (var conn = new OracleConnection(connString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
yield return new new Person(
Convert.ToInt32(reader["id"]),
reader["first_name"].ToString(),
reader["last_name"].ToString());
}
}
}
}
}
public IEnumerable RetrievePeople()
{
使用(var conn=新的OracleConnection(connString))
{
conn.Open();
使用(var cmd=conn.CreateCommand())
{
cmd.CommandText=查询;
使用(var reader=cmd.ExecuteReader())
{
while(reader.Read())
{
回报新人(
转换.ToInt32(读卡器[“id”]),
读取器[“first_name”]。ToString(),
读卡器[“姓氏].ToString());
}
}
}
}
}
通过这种方式,您不需要传递读取器,但是,在迭代器完成之前,连接将保持打开状态。这样做的好处是保留了读取器
的惰性评估方法,而不实际传递读取器,如果没有之后谁来清理连接的问题。你处理了连接。你处理了连接。不要忘记OracleDataReader
和OracleCommand`implementIDisposable
非常感谢Stuart,但是我有一个问题。这是一个很好的设计,使得DB操作类中的Person操作更大吗?PS:Person操作会更大。Person可以被视为某种类型的强类型DTO。大多数ORM都鼓励这种交互。您将人员
数据传递到您的体系结构上的距离取决于您。谢谢Stuart。这非常有帮助。不要忘记OracleDataReader
和OracleCommand`implementIDisposable
非常感谢Stuart,但是我有一个问题。这是一个很好的设计,使得DB操作类中的Person操作更大吗?PS:Person操作会更大。Person可以被视为某种类型的强类型DTO。大多数ORM都鼓励这种交互。通过人员
d提升架构的距离取决于您。谢谢Stuart。这非常有帮助。