This is a migrated thread and some comments may be shown as answers.

iObjectScope is already closed

13 Answers 260 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Marty Casey
Top achievements
Rank 1
Marty Casey asked on 27 Oct 2009, 10:29 PM
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();

      }

   }
}

13 Answers, 1 is accepted

Sort by
0
IT-Als
Top achievements
Rank 1
answered on 28 Oct 2009, 04:32 PM
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
0
Marty Casey
Top achievements
Rank 1
answered on 28 Oct 2009, 06:07 PM
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; }

}

}

0
IT-Als
Top achievements
Rank 1
answered on 29 Oct 2009, 07:25 AM
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


0
Dimitar Kapitanov
Telerik team
answered on 30 Oct 2009, 03:11 PM
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.
0
IT-Als
Top achievements
Rank 1
answered on 30 Oct 2009, 03:16 PM
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
0
Marty Casey
Top achievements
Rank 1
answered on 30 Oct 2009, 05:02 PM
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
0
Zoran
Telerik team
answered on 04 Nov 2009, 05:00 PM
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.
0
Gopinath
Top achievements
Rank 1
answered on 08 Nov 2012, 02:05 PM
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;
        }

0
Ady
Telerik team
answered on 12 Nov 2012, 11:56 AM
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.
0
Gopinath
Top achievements
Rank 1
answered on 13 Nov 2012, 01:03 PM
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

0
Ady
Telerik team
answered on 14 Nov 2012, 01:41 PM
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.
0
Gopinath
Top achievements
Rank 1
answered on 20 Nov 2012, 10:35 AM
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

}



0
Ady
Telerik team
answered on 23 Nov 2012, 09:49 AM
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.
Tags
General Discussions
Asked by
Marty Casey
Top achievements
Rank 1
Answers by
IT-Als
Top achievements
Rank 1
Marty Casey
Top achievements
Rank 1
Dimitar Kapitanov
Telerik team
Zoran
Telerik team
Gopinath
Top achievements
Rank 1
Ady
Telerik team
Share this question
or