Hi, I have implemented a WCF service that uses the DomainFactory, SessionProvidingBehavior and SessionProvidingInvoker as in the Xtensive.Storage examples. The domain gets build ok but having a Session instance is an issue.

I added a custom Session.Resolver that looks like this:

public static Session SessionResolver()
{
    Domain domain = GetDomain(); //standard DomainFactory.GetDomain()
    var session = domain.OpenSession();
    if (!session.IsActive)
        session.Activate();
    return session;
}

It seems to cause a loop. Using al these standard code and samples of X-Tensive, I wonder what I can and cannot do in this resolver. Could you clarify some things for me here? And maybe there is a standard resolver available within DO4.5 which can be used?

asked May 07 '12 at 10:39

Jos's gravatar image

Jos
44458


One Answer:

Hello, Jos

Your solution seems weird to me.

Let me explain some session activation magic first.

Any session in dataobjects.net could be made active. Active session is implicitly available via Session.Current static property. Behind the scene it is stored in [ThreadStatic] field so other threads are not affected. When no session is activated Session.Current default to invoking Session.Resolver delegate. This is made to allow storing session in some other implicitly available object. For example for ASP.NET applications it's typical to store session in HttpContext that is preserved across page rendering stages even threads are changed actively. For WCF application there is reason to use session resolver. You can simply activate session before invoking service method. SessionProvidingBehavior/SessionProvidingInvoker are simple extensions for WCF that allow you to create sessions for each call with simple attribute.

It's important to know that once session is activated reference to it is stored in thread-static field, so you should deactivate your session, when it is not longer required otherwise you will leak some memory. Session activation is stackable. This means you can activate many sessions, the most recently activated one would be returned by Session.Current

var session1 = ...
using (session1.Activate()) {
   // Session.Current returns session1 here
   var session2 = ...
   using (session2.Activate()) {
     // Session.Current returns session2 here
   } // session2 is deactivated at this moment
   // Session.Current returns session1 again
}

DataObjects.Net 4.5 do not activate sessions by default, so SessionProvidingInvoker should be changed to activate newly created session:

public object Invoke(object instance, object[] inputs, out object[] outputs)
{
  // Note that both Session and its "activation scope" are disposed property to avoid memory leaks
  using (var session = Session.Open(DomainFactory.GetDomain()))
  using (session.Activate()) {
    return originalInvoker.Invoke(instance, inputs, out outputs);
  }
}

You might also consider providing transaction as well:

public object Invoke(object instance, object[] inputs, out object[] outputs)
{
  using (var session = Session.Open(DomainFactory.GetDomain()))
  using (session.Activate())
  using (var tx = session.OpenTransaction()) {
    var result = originalInvoker.Invoke(instance, inputs, out outputs);
    tx.Complete();
    return result;
  }
}

answered May 08 '12 at 08:05

Denis%20Krjuchkov's gravatar image

Denis Krjuchkov
179325

edited May 08 '12 at 08:06

This is good information, thank you!

(May 08 '12 at 11:48) Jos Jos's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

powered by OSQA