连接自动处理

Ale*_*erD 4 .net c#

这看起来似乎微不足道,但它真的很困扰我.我今天开始在MVC项目中使用Dapper并创建了一个非常简单的POCO对象; 当我运行这个项目时,我收到以下错误消息:

无法访问已处置的对象

对象名称:'OracleConnection'.

这是代码:

public class MyController : Controller
{
    readonly IDbConnection sqlConn = new OracleConnection(ConfigurationManager.ConnectionStrings["LogDbContext"].ConnectionString);
    readonly string selectLog = "select * from LOG";
    readonly string insertLog = "insert into LOG (ID, Address) values (:ID, :Address)";

    // GET: Log
    public ActionResult Index()
    {
        using (sqlConn)
        {
            sqlConn.Open();

            //IEnumerable log = sqlConn.Query(selectLog);

            IEnumerable<Log> log = sqlConn.Query<Log>(selectLog);

            foreach (var item in log)
            {
                Console.WriteLine(item.ToString());
            }

        }

        return View();
    }

    public ActionResult Create()
    {
        using (sqlConn)
        {
            sqlConn.Open();

            var log = new Log()
            {
                ID = 1,
                Address = "test"
            };

            sqlConn.Execute(insertLog, log);

        }

        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

似乎将"sqlConn"放入using语句会使其自动处理,因此当函数再次运行时,它无法在连接上运行.

我怎么能阻止这个?我不希望每次需要时都手动打开和关闭连接.


UPDATE

使用下面答案提供的所有帮助(一切正确)我最后使用类的构造函数在每次必须使用类时实例化一个新连接.

    //removed the wrong static attribute and the instantiation
    readonly IDbConnection sqlConn;
    readonly string selectLog = "select * from LOG";
    readonly string insertLog = "insert into LOG (ID, Address) values (:ID, :Address)";

    // Created a constructor to instantiate the connection everytime the controller gets called
    public LogController()
    {
         sqlConn = new OracleConnection(ConfigurationManager.ConnectionStrings["LogDbContext"].ConnectionString);
    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 7

似乎将"sqlConn"放入using语句会使其自动处理

是的,这就是using声明的用途.

我怎么能阻止这个?我不希望每次需要时都手动打开和关闭连接.

我强烈建议你开放,每次你需要它的时候关闭连接-但使用它的局部变量,而不是一个领域.这样每个操作都会获得一个单独的逻辑连接,因此您不必担心线程问题等.让连接池负责提高效率.我怀疑你担心在每次调用时打开一个"物理"连接(建立一个新的TCP/IP连接或其他) - 但连接池是为了确保不会发生这种情况超出需要.

只需在方法中创建一个新连接:

using (var connection = new OracleConnection(...))
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

...并测量性能以确定它是否令人满意.不要开始猜测你是否会遇到问题(并采用导致比他们解决的更多问题的不良解决方法).

作为使用的替代方法new,控制器构造函数可以接受连接提供程序并要求新连接,但从根本上说它是关于每次创建新的一次性连接.

如果由于某种原因你真的,真的不想处理连接,只需删除using语句 - 但要非常清楚你需要自己处理并发.你几乎肯定不想那样做.


Ant*_*lev 6

您声明了sqlConnas static readonly,这意味着整个应用程序只有一个实例.将其包装using()意味着在第一个请求完成后,处理sqlConn被丢弃并且后续请求失败ObjectDisposedException.

要解决此问题,请按如下方式重写代码:

var connectionString = 
    ConfigurationManager.ConnectionStrings["LogDbContext"].ConnectionString;
using(var sqlConn = new OracleConnection(connectionString))
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

现在,至于你不想每次都打开连接,这就是你必须要做的.连接很珍贵,必须小心管理:尽可能晚开,一旦你不再需要就关闭.您始终可以将连接初始化逻辑分解为单独的方法,或者采用Enterprise(r)(tm)方式并将其注入.