C# 从数据库进行两次调用时出错
当我尝试使用相同的连接时,出现错误“无法访问一次性对象”。这就是我的Oracle上下文:C# 从数据库进行两次调用时出错,c#,asp.net-mvc,oracle,asp.net-mvc-3,C#,Asp.net Mvc,Oracle,Asp.net Mvc 3,当我尝试使用相同的连接时,出现错误“无法访问一次性对象”。这就是我的Oracle上下文: public class MyOracleContext { DbConnection connection; public MyOracleContext() { connection = new OracleConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].Connec
public class MyOracleContext
{
DbConnection connection;
public MyOracleContext()
{
connection = new OracleConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
}
public TOut ExecuteCommand<TOut>(IDbCommand command, Func<IDataReader, TOut> mapHelper)
{
TOut result = default(TOut);
try
{
using (connection)
{
using (command)
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (IDataReader reader = command.ExecuteReader(CommandBehavior.Default))
{
result = mapHelper(reader);
}
}
}
}
catch (Exception _exp)
{
throw new Exception("Error!" + _exp.Message);
}
return result;
}
public IDbCommand GetCommand()
{
OracleCommand cmd = (OracleCommand)connection.CreateCommand();
cmd.BindByName = true;
return cmd;
}
public IDataParameter GetParameter()
{
return new OracleParameter();
}
public bool ExecuteCommand(IDbCommand command)
{
bool result;
try
{
using (connection)
{
command.Prepare();
using (command)
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
result = command.ExecuteNonQuery() > 0;
}
}
}
catch (Exception _exp)
{
throw new Exception("Error!" + _exp.Message);
}
return result;
}
public DbParameter GetParameter(string name, object value)
{
OracleParameter para = new OracleParameter(name, value);
para.Size = int.MaxValue;
return para;
}
}
公共类MyOracleContext
{
数据库连接;
公共MyOracleContext()
{
连接=新的OracleConnection(ConfigurationManager.ConnectionString[“DefaultConnection”].ConnectionString);
}
public TOut ExecuteCommand(IDbCommand,Func mapHelper)
{
TOut结果=默认值(TOut);
尝试
{
使用(连接)
{
使用(命令)
{
if(connection.State!=ConnectionState.Open)
{
connection.Open();
}
使用(IDataReader reader=command.ExecuteReader(CommandBehavior.Default))
{
结果=mapHelper(读卡器);
}
}
}
}
捕获(例外情况)
{
抛出新异常(“错误!”+\u exp.Message);
}
返回结果;
}
公共IDbCommand GetCommand()
{
OracleCommand cmd=(OracleCommand)connection.CreateCommand();
cmd.BindByName=true;
返回cmd;
}
公共IDataParameter GetParameter()
{
返回新的OracleParameter();
}
public bool ExecuteCommand(IDbCommand)
{
布尔结果;
尝试
{
使用(连接)
{
command.Prepare();
使用(命令)
{
if(connection.State!=ConnectionState.Open)
{
connection.Open();
}
结果=command.ExecuteOnQuery()>0;
}
}
}
捕获(例外情况)
{
抛出新异常(“错误!”+\u exp.Message);
}
返回结果;
}
公共DbParameter GetParameter(字符串名称、对象值)
{
OracleParameter para=新的OracleParameter(名称、值);
参数大小=int.MaxValue;
返回段;
}
}
我使用ExecuteCommand从DB中获取结果,并使用ExecuteCommand,例如,Insert。但是,当我在同一方法上使用这两个命令时,当我进行连接时,会出现错误“无法访问一次性对象”。但是如果我按照相反的顺序(先使用ExecuteCommand,然后使用ExecuteCommand),它就会通过。问题是我想从BD获得结果,比较然后插入。知道为什么吗?我在这里被困了几个小时将“return result;”更改为using(){}
就像这样:
public TOut ExecuteCommand<TOut>(IDbCommand command, Func<IDataReader, TOut> mapHelper)
{
TOut result = default(TOut);
try
{
using (connection)
{
using (command)
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (IDataReader reader = command.ExecuteReader(CommandBehavior.Default))
{
return result = mapHelper(reader);
}
}
}
}
catch (Exception _exp)
{
throw new Exception("Error!" + _exp.Message);
}
}
public TOut ExecuteCommand(IDbCommand,Func-mapHelper)
{
TOut结果=默认值(TOut);
尝试
{
使用(连接)
{
使用(命令)
{
if(connection.State!=ConnectionState.Open)
{
connection.Open();
}
使用(IDataReader reader=command.ExecuteReader(CommandBehavior.Default))
{
返回结果=mapHelper(读卡器);
}
}
}
}
捕获(例外情况)
{
抛出新异常(“错误!”+\u exp.Message);
}
}
您将DbConnection
作为类的属性,但在执行命令后将其处理掉。如果随后使用同一实例执行另一个命令,则它试图使用已释放的连接
连接是由.NET汇集的,因此创建连接的成本相对较低。我只想在ExceuteCommand
方法中创建命令:
public TOut ExecuteCommand<TOut>(IDbCommand command, Func<IDataReader, TOut> mapHelper)
{
TOut result = default(TOut);
//try
//{
using (DbConnection connection = new OracleConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
//using (command)
//{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (IDataReader reader = command.ExecuteReader(CommandBehavior.Default))
{
result = mapHelper(reader);
}
//}
}
}
//catch (Exception _exp)
//{
// throw new Exception("Error!" + _exp.Message);
//}
return result;
}
public TOut ExecuteCommand(IDbCommand,Func-mapHelper)
{
TOut结果=默认值(TOut);
//试一试
//{
使用(DbConnection connection=new OracleConnection(ConfigurationManager.ConnectionString[“DefaultConnection”].ConnectionString))
{
//使用(命令)
//{
if(connection.State!=ConnectionState.Open)
{
connection.Open();
}
使用(IDataReader reader=command.ExecuteReader(CommandBehavior.Default))
{
结果=mapHelper(读卡器);
}
//}
}
}
//捕获(例外情况)
//{
//抛出新异常(“错误!”+\u exp.Message);
//}
返回结果;
}
我还建议进行另外两项修改:
- 您不应该在此方法中处理该命令,因为它没有创建该命令。任何负责创建一次性物品的东西都是 负责处理它李>
- 不要捕获任何异常,而只是简单地抛出另一个普通的
,只提取错误消息。要么让异常冒泡,要么做一些有意义的事情(记录它,添加更多的上下文,等等),然后抛出一个新异常,将原始异常附加为异常
,或者重新抛出异常InnerException
command.connection=connection
。这些类型的东西通常是命令和连接没有像这样抽象的原因-有足够的耦合,通常可以更干净地将它们管理在一起,即使这意味着一些代码重复。