System.ObjectDisposedException: 'Невозможно получить доступ к удаленному объекту. Имя объекта:' OracleConnection '.' - PullRequest
0 голосов
/ 26 ноября 2018

В следующем коде используются Entity Framework 6 и управляемые поставщики Oracle для вызова хранимой процедуры Oracle, которая возвращает несколько курсоров.

Оператор using вызывает следующее исключение:

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

Если я удаляю оператор using и вместо этого использую код в следующем посте.Я не получаю ошибок.

Использование Entity Framework для вызова хранимой процедуры Oracle с несколькими курсорами

Почему оператор using вызывает исключение?Мне было предложено, что есть ошибка с Oracle Managed Provider.Но мои коллеги используют одного и того же провайдера, и их операторы использования работают нормально.

Пример кода:

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 };
            }

        }
    }
}

1 Ответ

0 голосов
/ 26 ноября 2018

Правильно и правильно использовать using операторы вокруг одноразовых предметов , когда у вас есть время жизни ;однако, в этом случае: нет!Соединение здесь относится к контексту данных, и, предположительно, сам контекст данных равен IDisposable, и он будет располагать соединением, когда контекст данных расположен.

Итак:хотя вам может быть разрешено заимствовать соединение из контекста данных для выполнения запросов - вам не следует пытаться распоряжаться здесь.Это может привести к закрытию / удалению соединения в неожиданное время с непредсказуемыми результатами.


И наоборот: если у вас есть var conn = new OracleConnection(...), то, очевидно, вы делаете владеете это соединение (если вы не передадите его чему-то, что будет управлять временем жизни), и вы должны избавиться от него.


Просто чтобы еще больше усложнить ситуацию ... в настоящее время,ваш MyClass, кажется, владеет контекстом БД через:

private MyDbContext _dbContext = new MyDbContext();

Так что в идеале ваш MyClass должен быть одноразовым (: IDisposable), а располагаемый MyClass должен каскадно располагаться _dbContext.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...