Hi,

The [AspectBehavior(OpenTransaction = true)] does not work as expected : When entering a method with this attribute, I get a the following Exception : Unable to process operation without a transaction. Use Transaction.Open(...) to open it.

Here is some sample code :

[HierarchyRoot]
class Customer : Entity
{
    [Field, Key]
    public long Id { get; private set; }

    [Field]
    public string Name { get; set; }

    [AspectBehavior(OpenTransaction = true)]
    public void ChangeName(string newname)
    {
      Name = newname;
    }
}

in Main : 
[...]
      using (Session.Open(domain))
      {
        Customer foo;
        using (TransactionScope transactionScope = Transaction.Open())
        {
          foo = Query<Customer>.All.First();
          transactionScope.Complete(); 
        }
        // exception is thrown here : 
        foo.ChangeName("My new name"); 
      }

Apparently, the attribute does not open any transaction. Thank you for your feedback Best regards,

Auguste


Updated at 14.09.2009 14:46:29

Hi,

Thank you for your feedback

In this case [AspectBehavior] really shouldn't change anything: [...] Could you publish a complete stack trace? Does removal of attribute change the behavior?

No, the removal of the attribute does not change anything indeed. In fact, the bug is easy to reproduce. Please find hereafter the complete code needed to reproduce the bug. Version used is the latest nightly build available on 2009-09-11

namespace BuildDomain
{
  [HierarchyRoot]
  class Customer : Entity
  {
    [Field, Key]
    public long Id { get; private set; }

    [Field]
    public string Name { get; set; }

    public void ChangeName(string newname)
    {
      Name = newname;
    }
  }

  class Program
  {

    static void Main(string[] args)
    {
      DomainConfiguration DoConfiguration = new DomainConfiguration(@"sqlserver://localhost\SQLEXPRESS/DOtests");
      DoConfiguration.Types.Register(System.Reflection.Assembly.GetAssembly(typeof(Customer)));
      DoConfiguration.UpgradeMode = DomainUpgradeMode.Recreate;
      Domain domain = Domain.Build(DoConfiguration);
      Console.WriteLine("Domain is built.");

      using (Session.Open(domain))
      using (TransactionScope transactionScope = Transaction.Open())
      {
        Customer toto = new Customer { Name = "toto" };
        transactionScope.Complete();
      }

      Customer foo; 
      using (Session.Open(domain))
      {
        using (TransactionScope transactionScope = Transaction.Open())
        {
          foo = Query<Customer>.All.First();
          transactionScope.Complete(); 
        }
        foo.ChangeName("My new name"); 
      }

      Console.WriteLine("Press any key to exit");
      Console.ReadLine();
    }

  }
}

Here is the corresponding full stack trace

L'exception System.InvalidOperationException n'a pas été gérée
  Message="Unable to process operation without a transaction. Use Transaction.Open(...) to open it."
  Source="Xtensive.Storage"
  StackTrace:
       at Xtensive.Storage.Session.OpenTransaction(IsolationLevel isolationLevel, Boolean autoTransaction)
       at Xtensive.Storage.Session.OpenTransaction(Boolean autoTransaction)
       at Xtensive.Storage.Transaction.Open(Session session, Boolean autoTransaction)
       at Xtensive.Storage.Aspects.TransactionalAspect.OnEntry(Object instance)
       at BuildDomain.Customer.ChangeName(String newname) in D:\Perforce\aradus\Projets\ProjetsPerso\avenkiah\DO4\BuildDomain\BuildDomain\Program.cs:line 22
       at BuildDomain.Program.Main(String[] args) in D:\Perforce\aradus\Projets\ProjetsPerso\avenkiah\DO4\BuildDomain\BuildDomain\Program.cs:line 53
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

Updated at 15.09.2009 16:53:03

Thank you all for your feedback on this problem !

@Otto : Thank you very much for this fix.

@Alex : I am indeed interested with nightly builds and latest bug fixes !

In this case [AspectBehavior] really shouldn't change anything: - You can consider its default property values for any public SessionBound method are OpenTransaction = true, OpenSession = true

Given Otto's fix, I find it confusing that SessionOptions.AutoTransactions is off by default.

@Dimitri : I agree with you. Moreover, I find it easier to set the set options in DomainConfiguration : creating a new SessionConfiguration and adding it to DomainConfiguration.Sessions is not very straightforward. Anyway, it is easy use [AspectBehavior] to locally change the transactions behavior.

Best regards,

Auguste

This thread was imported from our support forum. The original discussion may contain more detailed answer.

asked Sep 11 '09 at 15:29

Auguste's gravatar image

Auguste
25888


One Answer:

otto wrote:

Hello Auguste,

I am also a user of DO4. As far as I know public methods/properties on a SessionBound derived class (Entity is that) need not be decorated with AspectBehavior, because they are automatically decorated by PostSharp at compile-time, so they will open a transaction if there is no one yet. Could you try it this way? Despite of this, the problem you showed will be probably answered or investigated.

Best regards, Otto


Alex (Xtensive) wrote:

In this case [AspectBehavior] really shouldn't change anything:

  • You can consider its default property values for any public SessionBound method are OpenTransaction = true, OpenSession = true

  • And on contrary, for any other method they are OpenTransaction = false, OpenSession = false

So that's why applying it in your case must not affect on anything. Probably, such "design" of [AspectBehavior] is wrong - I'll think how to change this to make it more clear.

Returning back you your issue: what's really strange is that there is no transaction. It must be.

Could you publish a complete stack trace? Does removal of attribute change the behavior?

The simplest way to check if method is really transactional is to study its C# code by .NET Reflector. There must be calls to TransactionalAspect.

Anyway, for now it looks much like a bug. The only possible your own error I imagine is case when this exception is thrown by some other code.


Alex (Xtensive) wrote:

Thank you a lot for such a comprehensive bug report - most likely, we'll fix the issue tomorrow.

If it will be possible, I will try to send you the most current build (there are few more important fixes). As you know, we don't update nightly builds for now, since we significantly change build process (no more necessity to install PostSharp + no more installation into GAC). So if I'll be able to finish this tomorrow, I'll send you new installer (I'm responsible for this). Otherwise I can send the binaries...


otto wrote:

This part of the code fails:

if (autoTransaction && !Configuration.AllowsAutoTransactions) throw new InvalidOperationException(Strings.ExTransactionRequired);

So I think the problem is that SessionConfiguration.AllowsAutoTransactions is false. You should create a SessionConfiguration in DomainConfig like this:

var sc = new SessionConfiguration("Default"); sc.AllowsAutoTransactions = true; domainConfig.Sessions.Add(sc);

The name "Default" is important, because this indicates that this sessionconfig will be used by default in your sessions.

BTW in sessionconfig you can set other things like cache size and so on.

Could you try this?


Alex (Xtensive) wrote:

Otto, thanks a lot for helping us. I fully forgot about this option.

Yes, by default automatic transactions are turned off. I.e. we always activate a Session (this.Session==Session.Current inside aspected SessionBound methods), but not always create a transaction. This depends on SessionOptions.

By default automatic transactions are off: we did this to ensure you will make a decision to use them or not by your own.


otto wrote:

I think the exception message should really mention this. And in the manual in the configuration/session part these options and other configuration details should be described. Including these special names ("Default", "Service", "KeyGenerator", "System") After this I think it is not needed to turn it on by default, because everybody can setup his own default sessionconfig.


Dmitri Maximov (Xtensive) wrote:

As for me, the configuration parameter should be contained in DomainConfiguration rather than in SessionConfiguration as it really influences the way a developer writes code for operations with transactional members (properties and methods). I mean the absence of necessity to write Transaction.Open regions.

If a developer prefers to use AutoTransactions = On mode, then he probably prefers to use this mode in EVERY session in his Domain. But current implementation enforces him to set this option manually in every SessionConfiguration instance. In simple scenarios this could be done by setting this option for Default SessionConfiguration, but only for simple scenarios with a few or even only one SessionConfiguration.


Alex (Xtensive) wrote:

Actually we're thinking about removing this option (AutoTransactions) at all... There is just one reason for disabling it: to identify all the places where transactions are created automatically rather than manually.

So likely, it will be a better idea to e.g. optionally log such transactions (it will be cheap taking into account logging performance) + add corresponding performance counters.


Alex (Xtensive) wrote:

Related issues:

answered Sep 11 '09 at 20:35

Editor's gravatar image

Editor
46156156157

otto wrote: BTW instead of "Default" it's better to write Xtensive.Storage.WellKnown.Sessions.Default

(Sep 11 '09 at 20:35) Editor Editor's gravatar image

otto wrote: Sorry, instead of

sc.AllowsAutoTransactions = true;

you should use this:

sc.Options |= SessionOptions.AutoTransactions;

(Sep 11 '09 at 20:35) Editor Editor's gravatar image

Btw... What do you think, what must be done? We can:

  • Turn them on by default

  • Write better exception message. It must explicitly state autotransactions are off now.

(Sep 11 '09 at 20:35) Alex Yakunin Alex%20Yakunin's gravatar image

otto wrote: Eventually it is good if there is a domain-level default for this setting. And if needed, it can be modified at session-level.

(Sep 11 '09 at 20:35) Editor Editor's gravatar image

I.e. likely, AutoTransaction will simply work everywhere. No configuration = less headache ;)

(Sep 11 '09 at 20:35) Alex Yakunin Alex%20Yakunin'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