iObjectScope is already closed

14 posts, 0 answers
  1. Marty Casey
    Marty Casey avatar
    4 posts
    Member since:
    Aug 2009

    Posted 27 Oct 2009 Link to this post

    I am new to this and I wasnt able to find an answer myself to this problem, I am not sure why the objetc I created outside the using Scope is losing data once I leave the using scope of the subsequesnt method call.

    THe call is an API function and I have a snippet of the unit test to test it which fails because of the iObjectScope error.

    Unit Test code (I dont know how to do the Format code block)
    ------------------
    IListQualifiersRequest actual;

    // lets get an object

     

    actual = target.GetQualifiersRequest(requestID, idleTimeLimit, hostSourceID, startingQualifier, securityToken);

    // all fields in object look good prior to call - see below

     

    target.CacheMFQualifiers(actual);

    //after call some field are exceptioned as iObjectScope is already closed

     

    Assert.AreEqual(requestID, actual.RequestID);

    //TODO determine why the following generate Telerik.OpenAccess.Exceptions.InvalidOperationException: The 'IObjectScope' is already closed

     

    Assert.AreEqual(hostSourceID, actual.HostSourceID);

    -----------------------------------

    public void CacheMFQualifiers(IListQualifiersRequest request)

    {

      var sql = "SELECT * FROM ListQualifiersRequestExtent " + "WHERE _requestID == $1";

     

      using (IObjectScope scope = XBDLPObjectScopeProvider.GetNewObjectScope())

      {

          var result = scope.GetOqlQuery(sql).Execute(request.RequestID);

          if (result.Count == 0)

          {

              scope.Transaction.Begin();

              scope.Add(request);

              scope.Transaction.Commit();

          }

       }
    }

  2. TSE
    TSE avatar
    381 posts
    Member since:
    Sep 2008

    Posted 28 Oct 2009 Link to this post

    Hi Marty,

    One thing I could think of would be that OA lazy loads a field, and because the scope you used to load the instance is disposed (by leaving the using block) you get an exception when OA tries to do so.
    However, I cannot be sure that this is actually the reason. Maybe you can post your interface IListQualifiersRequest?

    Regards

    Henrik
  3. DevCraft banner
  4. Marty Casey
    Marty Casey avatar
    4 posts
    Member since:
    Aug 2009

    Posted 28 Oct 2009 Link to this post

    here is the object and its interface

    namespace

    XBDLP.Interface

    {

    public interface IListQualifiersRequest:IDLPRequest

     

    {

    Guid HostSourceID { get;}

    string StartingQualifier { get;}

    IListQualifiersStatus Status { get; }

    }

    }



    [Telerik.OpenAccess.Persistent()]

    public class ListQualifiersRequest:DLPRequestBase,IListQualifiersRequest

     

    {

    private Guid _hostSourceID;

    private string _startingQualifier;

    private ListQualifiersStatus _status;

    private ListQualifiersRequest()

    {

    }

    public ListQualifiersRequest(Guid requestID, int? idleTimeLimit, Guid hostSourceID, string startingQualifier, DSSecurityToken token)

    : base(requestID, token)

    {

    _hostSourceID = hostSourceID;

    _startingQualifier = startingQualifier;

    _status = new ListQualifiersStatus(requestID, idleTimeLimit);

    }

    public Guid HostSourceID

    {

    get { return _hostSourceID; }

    }

    public string StartingQualifier

    {

    get { return _startingQualifier; }

    }

    public IListQualifiersStatus Status

    {

    get { return _status; }

    }

    }

    Base class and intrerface

     

    namespace

    XBDLP.Interface

    {

    public interface IDLPRequest

     

     

     

    {

    Guid RequestID { get; }

    string RequestedBy { get; }

    DateTime WhenRequested { get; }

    }

    }

    [Telerik.OpenAccess.Persistent(IdentityField = "_requestID")]

    public class DLPRequestBase: IDLPRequest

     

     

     

    {

    private Guid _requestID;

    private string _requestedBy;

    private DateTime _whenRequested;

    internal DLPRequestBase()

    {

     

    }

    public DLPRequestBase(Guid? requestID, DSSecurityToken token)

    {

    if (requestID == null)

    {

    _requestID = Guid.NewGuid();

    }

    else

     

     

     

    {

    _requestID = requestID.Value;

    }

    _whenRequested = DateTime.Now;

    _requestedBy = token._userName;

    }

    public Guid RequestID

    {

    get { return _requestID; }

    }

    public string RequestedBy

    {

    get { return _requestedBy; }

    }

    public DateTime WhenRequested

    {

    get { return _whenRequested; }

    }

    }

  5. TSE
    TSE avatar
    381 posts
    Member since:
    Sep 2008

    Posted 29 Oct 2009 Link to this post

    Hi Marty,

    If I understand you correct it the line:

    Assert.AreEqual(hostSourceID, actual.HostSourceID);

    that generates the exception.

    Since, this is a unit test (don't know which framework you use), you really should consider obtaining the scope when initializing the unit test and dispose it again when you finalize the unit test... In most unit test frameworks there's a place to do such stuff..

    This will keep the scope alive during the unit test and you will not get this error... It is definately caused by lazy loading and the fact that the scope used to create the object is disposed.

    Regards

    Henrik


  6. Dimitar Kapitanov
    Admin
    Dimitar Kapitanov avatar
    632 posts

    Posted 30 Oct 2009 Link to this post

    Hi hgsdc,
    Additional information regarding how to use Telerik OpenAccess ORM can be found here.

    Best wishes,
    Dimitar Kapitanov
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  7. TSE
    TSE avatar
    381 posts
    Member since:
    Sep 2008

    Posted 30 Oct 2009 Link to this post

    Hey Ditmar,

    Thank for the link. I was already aware of it, since we use MS unit test framework for our unit test.

    The basic idea though is to keep the object scope alive during tests.

    Cheers,

    Henrik
  8. Marty Casey
    Marty Casey avatar
    4 posts
    Member since:
    Aug 2009

    Posted 30 Oct 2009 Link to this post

    Hi Ditmar,

    Henrik is right. We have many tests but in the particialur case the object that is getting passed into the tested method is returning with some data removed after the scope was used in the tested method.

    SInce the object was created outside the Using scope block I am not sure why some (not all) data in the object was getting trashed as it appears is happening.

    Marty
  9. Zoran
    Admin
    Zoran avatar
    534 posts

    Posted 04 Nov 2009 Link to this post

    Hi Marty Casey,

    The more probable scenario is that the data is not being trashed as you assume but it has never been loaded. Since OpenAccess uses the lazy loading mechanism, trying to access an unloaded data requires an object scope to manage such operation. Hence, disposing of your scope leads to the exception you are getting..

    Nevertheless, you should be able to instantiate a static scope for your test class in a ClassInitialize method which runs before any of the tests have started and then dispose after all the tests have ran.

    Regards,
    Zoran
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  10. Gopinath
    Gopinath avatar
    21 posts
    Member since:
    Dec 2011

    Posted 08 Nov 2012 Link to this post

    Hello,

    This is how I handle IObjectscope. I am also getting an error IObjectscope is alread closed. Could you please advice the below code needs an change.

     static public IObjectScope ObjectScope()
            {
                Database();

                if (_theObjectScopeProvider._myScope == null)
                {
                    _theObjectScopeProvider._myScope = GetNewObjectScope();
                }

                return _theObjectScopeProvider._myScope;
            }

            static public IObjectScope GetNewObjectScope()
            {
                var db = Database();

                db.Properties.ConnectionTimeout = 0;

     

     

     

                var newScope = db.GetObjectScope();

                return newScope;
            }

            static public Database Database()
            {
                if (_theObjectScopeProvider == null)
                {
                    _theObjectScopeProvider = new ObjectScopeProvider();
                }

                if (_theObjectScopeProvider._myDatabase == null)
                {
                    _theObjectScopeProvider._myDatabase = Telerik.OpenAccess.Database.Get("OracleConnection", OpenAccessConfigurationHandler.ConfigOverride);
                }

                return _theObjectScopeProvider._myDatabase;
            }

  11. Ady
    Admin
    Ady avatar
    589 posts

    Posted 12 Nov 2012 Link to this post

    Hello Gopinath,

     This code is how you obtain the IObjectScope instance. I would be interested in seeing how you are using the obtained instance. The exception indicates that you are trying to use an already dispose IObjectScope instance.

    Kind regards,
    Ady
    the Telerik team
    Telerik OpenAccess ORM Meets ASP.NET Web API. Read more.
  12. Gopinath
    Gopinath avatar
    21 posts
    Member since:
    Dec 2011

    Posted 13 Nov 2012 Link to this post

    Hello,

    In server, we use structuremap something like this:

    For<

    IObjectScope>() .LifecycleIs(new WcfInstanceContextLifecycle())

     .Add(ctx => ObjectScopeProvider.GetNewObjectScope()); 
     

    WcfInstanceContextLifecycle is a custom ILifecycle for the StructureMap framework for scoping instances to the lifetime of a WCF call. This is the foundation for enabling session per request over WCF.

    Thanks

  13. Ady
    Admin
    Ady avatar
    589 posts

    Posted 14 Nov 2012 Link to this post

    Hi Gopinath,

     Unfortunately the usage code does not tell me much. The reason for this exception is that the IObjectScope instance is already disposed when you try to use it to perform CRUD operations. Can you try and find out when the obtained scope is disposed by the StructureMap framework?


    Greetings,
    Ady
    the Telerik team
    Telerik OpenAccess ORM Meets ASP.NET Web API. Read more.
  14. Gopinath
    Gopinath avatar
    21 posts
    Member since:
    Dec 2011

    Posted 20 Nov 2012 Link to this post

    let me try again. This is the method which collects the objects from container and distributed across all active clients. In the line GetObjectId, sometimes I get 'connection pool is closed or Iobject scope already closed. please see if that helps you find out the issue.

    private

    static ObjectContainer Prepare(ObjectContainer container)

    {

    var resultContainer = new ObjectContainer();

    using(var scopeBlock = ObjectScopeProvider.GetNewScopeBlock())

    {

    var idsToBeDistributed = container.Extent<object>() .Where(x => x.IsOf<INeedDistribution>() && IsPersistant(container, x))

     .Select(x => container.GetObjectId(x))

    .ToList();

     

     var refreshedObjects = idsToBeDistributed.Select(id => scopeBlock.Scope.GetObjectById(id)).ToList();

     resultContainer.CopyFrom(scopeBlock.Scope,

     string.Empty,

     refreshedObjects,

     new FetchGroupCollector(FetchGroupCollector.DefaultFetchGroup));

     }

     

    return resultContainer;

     

    }


    definition of Objectscopeblock class:

    internal

    sealed class ObjectScopeBlock : IObjectScopeBlock

     {

     

     

    public ObjectScopeBlock(IObjectScope scope)

     {

      

    Contract.RequiresNonNullArgument(scope, "scope");

     Scope = scope;

    }

    #region

     

     

    IObjectScopeBlock Members

     

    public IObjectScope Scope { get; private set; }

     

    /// <summary>

    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

    /// </summary>

     

    public void Dispose()

    {

    if (Scope == null)

     {

     return;

     }

    Scope.Dispose();

    Scope =  null;

      

    ObjectScopeProvider.ResetDbConnectionTimeout();

     }

    #endregion

    }



  15. Ady
    Admin
    Ady avatar
    589 posts

    Posted 23 Nov 2012 Link to this post

    Hello Gopinath,

     The code looks fine. How is the ObjectContainer that is passed into the 'Prepare' method handled. If the 'container.GetObjectId' method throws the exception the underlying scope of the container seems to be disposed.
    Can you prepare a sample application that reproduces this exception? This would help in resolving the issue sooner.

    All the best,
    Ady
    the Telerik team
    Telerik OpenAccess ORM Meets ASP.NET Web API. Read more.
Back to Top
DevCraft banner