簡體   English   中英

System.ObjectDisposedException:'無法訪問已處置的對象。對象名稱:'OracleConnection'。

[英]System.ObjectDisposedException: 'Cannot access a disposed object.Object name: 'OracleConnection'.'

以下代碼使用Entity Framework 6和Managed Oracle Providers來調用返回多個游標的Oracle存儲過程。

using語句引發以下異常:

 System.ObjectDisposedException: 'Cannot access a disposed object.Object name: 'OracleConnection'.'

如果我刪除了using語句,而是使用以下帖子中的代碼。 我沒有錯誤。

使用實體框架調用具有多個游標的Oracle存儲過程

為什么using語句導致異常? 我建議Oracle托管提供程序存在錯誤。 但是,我的同事正在使用同一個提供程序,並且他們的using語句工作正常。

示例代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using Oracle.ManagedDataAccess.Client;
using System.Data.Entity.Infrastructure;

namespace MyCompany
{
    public class MyClass
    {
        private MyDbContext _dbContext = new MyDbContext();

        public MyItems GetMyItems(string id)
        {
            var sqlQuery = "";
            var oracleParameters = new List<OracleParameter>();
            var oneEntityList = new List<OneEntity>();
            var twoEntityList = new List<TwoEntity>();
            var threeEntityList = new List<ThreeEntity>();

            sqlQuery = @"

BEGIN 

MY_PACKAGE.GetMyItems(:id, :p_cursor1, :p_cursor2, :p_cursor3);

END;

";
            oracleParameters = new List<OracleParameter>
            {
                new OracleParameter("p_id", id),
                new OracleParameter("p_cursor1", OracleDbType.RefCursor, ParameterDirection.Output),
                new OracleParameter("p_cursor2", OracleDbType.RefCursor, ParameterDirection.Output),
                new OracleParameter("p_cursor3", OracleDbType.RefCursor, ParameterDirection.Output)
            };

            using (var connection = _dbContext.Database.Connection)
            {          
                connection.Open();
                var command = connection.CreateCommand();
                command.CommandText = sqlQuery;
                command.Parameters.AddRange(oracleParameters.ToArray());
                using (var reader = command.ExecuteReader())
                {
                    oneEntityList = ((IObjectContextAdapter)dbContext).ObjectContext
                                                                                .Translate<OneEntity>(reader)
                                                                                .ToList();
                    reader.NextResult();

                    twoEntityList = ((IObjectContextAdapter)dbContext).ObjectContext
                                                                                .Translate<TwoEntity>(reader)
                                                                                .ToList();
                    reader.NextResult();

                    threeEntityList = ((IObjectContextAdapter)dbContext).ObjectContext
                                                                                .Translate<ThreeEntity>(reader)
                                                                                .ToList();
                }

                return new MyItems { OneEntity = oneEntityList, TwoEntity = twoEntityList, ThreeEntity = threeEntityList };
            }

        }
    }
}

當您擁有生命周期時,在可拋棄對象周圍using語句是正確和適當 但是,在這種情況下:您不會! 這里的連接屬於數據上下文,並且假定數據上下文本身是IDisposable ,並且在處理數據上下文時將處理連接。

因此:盡管出於執行查詢的目的,您可能被允許從數據上下文中借用連接,但是您不應該嘗試在此處處置它。 最終將在意外的時間關閉/部署連接,從而產生不可預測的結果。


相反:如果您有一個var conn = new OracleConnection(...) ,那么顯然您確實擁有連接(除非您將其交給可以管理生命周期的對象),並且應該對其進行處置。


只是為了使事情更加復雜...目前,您的MyClass似乎通過以下方式擁有db-context:

private MyDbContext _dbContext = new MyDbContext();

因此,理想情況下, MyClass應該是可拋棄的( : IDisposable ),而_dbContext MyClass應該級聯以部署_dbContext

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM