Hi,

Maybe I'm missing something. We sometimes get exceptions like the one below. In this case the following code was executed:

var query =from dossierstatustype in Query.All<DossierStatusType>()
                where dossierstatustype.Z_IsDefault
                select dossierstatustype;

                List<DossierStatusType> defaults = query.ToList();

The query.ToList() throws the following exception:

InvalidOperationException: Unable to process operation without a transaction. Use Transaction.Open(...) to open it. Xtensive.Storage.dll!Xtensive.Storage.TransactionalStateContainer<xtensive.core.tuples.tuple>.BindToCurrentTransaction(bool skipValidation = false) + 0xa7 bytes
Xtensive.Storage.dll!Xtensive.Storage.TransactionalStateContainer<xtensive.core.tuples.tuple>.BindToCurrentTransaction() + 0x2a bytes
Xtensive.Storage.dll!Xtensive.Storage.EntityState.PersistenceState.set(Xtensive.Storage.PersistenceState value = Removed) + 0xac bytes
Xtensive.Storage.dll!Xtensive.Storage.Entity.SystemInitializationError(System.Exception error = {"Error 'Unknown'. Original message: Der Transaktionsvorgang kann nicht ausgeführt werden, weil es ausstehende Anforderungen im Rahmen dieser Transaktion gibt."}) + 0x160 bytes
Translates to: The transaction operation cannot be performed because there are pending requests working on this transaction Xtensive.Storage.dll!Xtensive.Storage.Persistent.InitializationError(System.Type ctorType = {Name = "Entity" FullName = "Xtensive.Storage.Entity"}, System.Exception error = {"Error 'Unknown'. Original message: Der Transaktionsvorgang kann nicht ausgeführt werden, weil es ausstehende Anforderungen im Rahmen dieser Transaktion gibt."}) + 0x49 bytes
Xtensive.Storage.dll!Xtensive.Storage.Entity.Entity(Xtensive.Storage.EntityState state = Key = {Xtensive.Storage.Internals.Key<int>}, Tuple = {Xtensive.Core.Tuples.DifferentialTuple}, PersistenceState = Removed) + 0x10b bytes
KLIBDatabase.dll!Diartis.KLIB.Model.AbstractEntity.AbstractEntity(Xtensive.Storage.EntityState arg0 = Key = {Xtensive.Storage.Internals.Key<int>}, Tuple = {Xtensive.Core.Tuples.DifferentialTuple}, PersistenceState = Removed) + 0x35 bytes
KLIBDatabase.dll!Diartis.KLIB.Model.DossierStatusType.DossierStatusType(Xtensive.Storage.EntityState arg0 = Key = {Xtensive.Storage.Internals.Key<int>}, Tuple = {Xtensive.Core.Tuples.DifferentialTuple}, PersistenceState = Removed) + 0x35 bytes KLIBDatabase.dll!Diartis.KLIB.Model.DossierStatusType.~Xtensive.Core.Aspects.FactoryMethod(Xtensive.Storage.EntityState arg0 = Key = {Xtensive.Storage.Internals.Key<int>}, Tuple = {Xtensive.Core.Tuples.DifferentialTuple}, PersistenceState = Removed) + 0x4a bytes
Xtensive.Storage.dll!Xtensive.Storage.Internals.Activator.CreateEntity(System.Type type = {Name = "DossierStatusType" FullName = "Diartis.KLIB.Model.DossierStatusType"}, Xtensive.Storage.EntityState state = Key = {Xtensive.Storage.Internals.Key<int>}, Tuple = {Xtensive.Core.Tuples.DifferentialTuple}, PersistenceState = Removed) + 0x128 bytes Xtensive.Storage.dll!Xtensive.Storage.EntityState.Entity.get() + 0x90 bytes Xtensive.Storage.dll!Xtensive.Storage.Linq.Materialization.ItemMaterializationContext.Materialize(int entityIndex = 0, int typeIdIndex = 1, Xtensive.Storage.Model.TypeInfo type = {System.RuntimeType}, Xtensive.Core.Pair<int>[] entityColumns = {Xtensive.Core.Pair<int>[17]}, Xtensive.Core.Tuples.Tuple tuple = {Xtensive.Core.Tuples.Internals.Tuple<int,int,system.datetime,int,system.datetime,int,bool,string,string,string,string,bool,string,bool,bool,bool,int>}) + 0x3dc bytes [Lightweight Function]
Xtensive.Core.dll!Xtensive.Core.DelegateBindExtensions.Bind<object[],xtensive.core.tuples.tuple,xtensive.storage.linq.materialization.itemmaterializationcontext,diartis.klib.model.dossierstatustype>.AnonymousMethod9(Xtensive.Core.Tuples.Tuple arg2 = {Xtensive.Core.Tuples.Internals.Tuple<int,int,system.datetime,int,system.datetime,int,bool,string,string,string,string,bool,string,bool,bool,bool,int>}, Xtensive.Storage.Linq.Materialization.ItemMaterializationContext arg3 = {Xtensive.Storage.Linq.Materialization.ItemMaterializationContext}) + 0x5a bytes
Xtensive.Storage.dll!Xtensive.Storage.Linq.Materialization.MaterializationHelper.Materialize<diartis.klib.model.dossierstatustype>.AnonymousMethod
3(Xtensive.Core.Tuples.Tuple tuple = {Xtensive.Core.Tuples.Internals.Tuple<int,int,system.datetime,int,system.datetime,int,bool,string,string,string,string,bool,string,bool,bool,bool,int>}) + 0x95 bytes
System.Core.dll!System.Linq.Enumerable.WhereSelectEnumerableIterator<xtensive.core.tuples.tuple,diartis.klib.model.dossierstatustype>.MoveNext() + 0xee bytes
Xtensive.Core.dll!Xtensive.Core.EnumerableExtensions.Batch<diartis.klib.model.dossierstatustype>.MoveNext() + 0x3b6 bytes
Xtensive.Core.dll!Xtensive.Core.EnumerableExtensions.ApplyBeforeAndAfter<diartis.klib.model.dossierstatustype>.MoveNext() + 0x165 bytes Xtensive.Storage.dll!Xtensive.Storage.TransactionalExtensions.ToTransactional<system.collections.generic.ienumerable<diartis.klib.model.dossierstatustype>>.MoveNext() + 0x2be bytes
System.Core.dll!System.Linq.Enumerable.SelectManyIterator<system.collections.generic.ienumerable<diartis.klib.model.dossierstatustype>,Diartis.KLIB.Model.DossierStatusType>.MoveNext() + 0x242 bytes
mscorlib.dll!System.Collections.Generic.List<diartis.klib.model.dossierstatustype>.List(System.Collections.Generic.IEnumerable<diartis.klib.model.dossierstatustype> collection) + 0x1d8 bytes
System.Core.dll!System.Linq.Enumerable.ToList<diartis.klib.model.dossierstatustype>(System.Collections.Generic.IEnumerable<diartis.klib.model.dossierstatustype> source) + 0x50 bytes

KLIBDatabase.dll!Diartis.KLIB.Model.DossierStatusType.GetDefaultDossierStatusType(bool mandatory = true) Line 150 + 0x11 bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.DossierStatusType.Default.get() Line 124 + 0x7 bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.DossierStatus.OnInitializing(Diartis.KLIB.Model.AbstractEntity.EntityInitializationMode mode = Created) Line 34 + 0x17 bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.DossierContacting.OnInitializing(Diartis.KLIB.Model.AbstractEntity.EntityInitializationMode mode = Created) Line 32 + 0x14 bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.AbstractEntity.InitializeMembers(Diartis.KLIB.Model.AbstractEntityCreateArguments createArgumentsIn = null) Line 320 + 0x1a bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.AbstractEntity.OnInitialize() Line 297 + 0x13 bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.AbstractHistory.OnInitialize() Line 215 + 0xa bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.AbstractSequenceHistory.OnInitialize() Line 175 + 0xa bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.DossierStatus.OnInitialize() Line 256 + 0xa bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.DossierContacting.OnInitialize() Line 285 + 0xa bytes C# Xtensive.Storage.dll!Xtensive.Storage.Entity.SystemInitialize(bool materialize = false) + 0x10f bytes
Xtensive.Storage.dll!Xtensive.Storage.Persistent.Initialize(System.Type ctorType = {Name = "DossierContacting" FullName = "Diartis.KLIB.Model.DossierContacting"}) + 0x80 bytes KLIBDatabase.dll!Diartis.KLIB.Model.DossierContacting.DossierContacting(Diartis.KLIB.Model.DossierContactingCreateArguments createArguments = null) Line 281 + 0x20 bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.Dossier.AddDossierStatusDossierContacting(Diartis.KLIB.Model.DossierContactingCreateArguments createArguments = null) Line 2490 + 0x25 bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.Dossier.AddDossierStatusDossierContacting() Line 2482 + 0xb bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.Dossier.AddDefaultStatusIfNone() Line 130 + 0xa bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.Dossier.OnInitializing(Diartis.KLIB.Model.AbstractEntity.EntityInitializationMode mode = Created) Line 78 + 0xa bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.AbstractEntity.InitializeMembers(Diartis.KLIB.Model.AbstractEntityCreateArguments createArgumentsIn = null) Line 320 + 0x1a bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.AbstractEntity.OnInitialize() Line 297 + 0x13 bytes C# KLIBDatabase.dll!Diartis.KLIB.Model.Dossier.OnInitialize() Line 991 + 0xa bytes C# Xtensive.Storage.dll!Xtensive.Storage.Entity.SystemInitialize(bool materialize = false) + 0x10f bytes
Xtensive.Storage.dll!Xtensive.Storage.Persistent.Initialize(System.Type ctorType = {Name = "Dossier" FullName = "Diartis.KLIB.Model.Dossier"}) + 0x80 bytes KLIBDatabase.dll!Diartis.KLIB.Model.Dossier.Dossier() Line 980 + 0x20 bytes C# KLIBViewModel.dll!Diartis.KLIB.KLIBViewModel.VMDossier.CreateDossier() Line 1680 + 0x25 bytes C# KLIBViewModel.dll!Diartis.KLIB.KLIBViewModel.VMDossier.Construct(Diartis.KLIB.KLIBViewModel.EntityConstructionMode entityConstructionMode = Create, int dossierId = -1, Diartis.KLIB.Model.AbstractEntity entity = null) Line 1431 + 0xa bytes C# KLIBViewModel.dll!Diartis.KLIB.KLIBViewModel.VMEntity.VMEntity(Diartis.KLIB.KLIBViewModel.EntityConstructionMode entityConstructionMode = Create, int id = -1, Diartis.KLIB.Model.AbstractEntity entity = null) Line 346 + 0x21 bytes C# KLIBViewModel.dll!Diartis.KLIB.KLIBViewModel.VMAbstractEntity.VMAbstractEntity(Diartis.KLIB.KLIBViewModel.EntityConstructionMode entityConstructionMode = Create, int abstractEntityId = -1, Diartis.KLIB.Model.AbstractEntity abstractEntity = null) Line 314 + 0x18 bytes C# KLIBViewModel.dll!Diartis.KLIB.KLIBViewModel.VMDossier.VMDossier(Diartis.KLIB.KLIBViewModel.EntityConstructionMode entityConstructionMode = Create, int dossierId = -1, Diartis.KLIB.Model.Dossier dossier = null) Line 781 + 0x24 bytes C# KLIBViewModel.dll!Diartis.KLIB.KLIBViewModel.VMDossier.VMDossier() Line 770 + 0x18 bytes C# KLIBViewModel.dll!Diartis.KLIB.KLIBViewModel.VMMaintenanceDossier.VMMaintenanceDossier() Line 12 + 0xa bytes C# [Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.RuntimeType.CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache) + 0x75 bytes
mscorlib.dll!System.Activator.CreateInstance<diartis.klib.klibviewmodel.vmmaintenancedossier>() + 0x58 bytes
KLIBBase.dll!Diartis.KLIB.KLIBControls.KLIBMaintenanceControl<diartis.klib.klibviewmodel.vmmaintenancedossier>.KLIBMaintenanceControl() Line 142 + 0x60 bytes C# KLIBMasksDossier.dll!Diartis.KLIB.Masks.Dossier.KLIBDossierMainPanelShape.KLIBDossierMainPanelShape() Line 16 + 0xa bytes C# KLIBMasksDossier.dll!Diartis.KLIB.Masks.Dossier.KLIBDossierMainPanel.KLIBDossierMainPanel() Line 33 + 0xa bytes C# KLIBMasksDossier.dll!Diartis.KLIB.Masks.Dossier.KLIBDossierTabItem.KLIBDossierTabItem() Line 34 + 0x2f bytes C# KLIB.exe!Diartis.KLIB.MainWindow.OnNewDossier(object target = {Diartis.KLIB.MainWindow}, System.Windows.Input.ExecutedRoutedEventArgs e = {System.Windows.Input.ExecutedRoutedEventArgs}) Line 298 + 0x25 bytes C# PresentationCore.dll!System.Windows.Input.CommandBinding.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) + 0xe2 bytes PresentationCore.dll!System.Windows.Input.CommandManager.ExecuteCommandBinding(object sender, System.Windows.Input.ExecutedRoutedEventArgs e = {System.Windows.Input.ExecutedRoutedEventArgs}, System.Windows.Input.CommandBinding commandBinding) + 0xd2 bytes PresentationCore.dll!System.Windows.Input.CommandManager.FindCommandBinding(System.Windows.Input.CommandBindingCollection commandBindings, object sender, System.Windows.RoutedEventArgs e, System.Windows.Input.ICommand command, bool execute) + 0x100 bytes
PresentationCore.dll!System.Windows.Input.CommandManager.FindCommandBinding(object sender, System.Windows.RoutedEventArgs e, System.Windows.Input.ICommand command, bool execute) + 0x234 bytes PresentationCore.dll!System.Windows.Input.CommandManager.OnExecuted(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) + 0x3a bytes PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) + 0x53 bytes
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised) + 0x271 bytes
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender = {Diartis.KLIB.KLIBControlLibrary.StandardControls.KLIBRibbonButton}, System.Windows.RoutedEventArgs args = {System.Windows.Input.ExecutedRoutedEventArgs}) + 0x14e bytes
PresentationCore.dll!System.Windows.Input.RoutedCommand.ExecuteImpl(object parameter, System.Windows.IInputElement target, bool userInitiated) + 0x17f bytes
ActiproSoftware.Ribbon.Wpf351.dll!ActiproSoftware.Windows.Controls.Ribbon.Input.RibbonCommand.a(System.Windows.Input.ICommandSource A_0 = {Diartis.KLIB.KLIBControlLibrary.StandardControls.KLIBRibbonButton}) + 0x128 bytes
ActiproSoftware.Ribbon.Wpf351.dll!ActiproSoftware.Windows.Controls.Ribbon.Controls.Primitives.ControlBase.OnClick(ActiproSoftware.Windows.Controls.Ribbon.Controls.ExecuteRoutedEventArgs e = {ActiproSoftware.Windows.Controls.Ribbon.Controls.ExecuteRoutedEventArgs}) + 0x84 bytes
ActiproSoftware.Ribbon.Wpf351.dll!ActiproSoftware.Windows.Controls.Ribbon.Controls.Primitives.ButtonBase.OnClick(ActiproSoftware.Windows.Controls.Ribbon.Controls.ExecuteRoutedEventArgs e = {ActiproSoftware.Windows.Controls.Ribbon.Controls.ExecuteRoutedEventArgs}) + 0x7a bytes
ActiproSoftware.Ribbon.Wpf351.dll!ActiproSoftware.Windows.Controls.Ribbon.Controls.Primitives.ControlBase..a(object A_0 = true) + 0x50 bytes
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x5a bytes WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate method, object args, int numArgs, System.Delegate catchHandler = null) + 0x47 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke(System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) + 0x5d bytes
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() + 0xb5 bytes
mscorlib.dll!System.Threading.ExecutionContext.runTryCode(object userData) + 0x178 bytes
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xa1 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x3b bytes
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke() + 0x6d bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue() + 0x27f bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0xb3 bytes WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x160 bytes
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x97 bytes
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x5a bytes WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate method, object args, int numArgs, System.Delegate catchHandler = null) + 0x47 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke(System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) + 0x5d bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) + 0xe8 bytes
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) + 0x164 bytes
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0x13a bytes PresentationFramework.dll!System.Windows.Window.ShowHelper(object booleanBox) + 0x20f bytes PresentationFramework.dll!System.Windows.Window.ShowDialog() + 0x5be bytes
KLIB.exe!Diartis.KLIB.App.ApplicationStartup(object sender = {Diartis.KLIB.App}, System.Windows.StartupEventArgs e = {System.Windows.StartupEventArgs}) Line 66 + 0x10 bytes C# KLIB.exe!Diartis.KLIB.App.OnStartup(System.Windows.StartupEventArgs e = {System.Windows.StartupEventArgs}) Line 134 + 0xf bytes C# PresentationFramework.dll!System.Windows.Application..ctor.AnonymousMethod__1(object unused) + 0x53 bytes
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x5a bytes WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate method, object args, int numArgs, System.Delegate catchHandler = null) + 0x47 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke(System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) + 0x5d bytes
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() + 0xb5 bytes
mscorlib.dll!System.Threading.ExecutionContext.runTryCode(object userData) + 0x178 bytes
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xa1 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x3b bytes
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke() + 0x6d bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue() + 0x27f bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0xb3 bytes WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x160 bytes
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x97 bytes
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x5a bytes WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate method, object args, int numArgs, System.Delegate catchHandler = null) + 0x47 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke(System.Delegate callback, object args, int numArgs, System.Delegate catchHandler) + 0x5d bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) + 0xe8 bytes
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) + 0x164 bytes
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0x13a bytes PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x195 bytes
PresentationFramework.dll!System.Windows.Application.Run() + 0x67 bytes KLIB.exe!Diartis.KLIB.App.Main() + 0x77 bytes C# [Native to Managed Transition]
[Managed to Native Transition]
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x48 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xdc bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x3b bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x4d bytes
[Native to Managed Transition]

Do we need to open a transaction?

Regards Paul Sinnema diartis AG


Updated at 08.07.2010 15:34:33

Let me give you some more code. Here's what we call our ModelContext. In the ModelContext we open the Configuration, Domain and Session with DisconnectedState. In the Constructor of the Class the Session is opened and in the Dispose() of the Class the Session and the other objects are disposed. We use the 'SessionEntityChanging' event to gather all changed entities. In the OnSaving the gathered Entities are used to add a Stamp with time and user that changed/created the Entity and to do some final adjustments (OnInitializing call). In the OnSaved we also give classes the opertunity to do some after save processing using the same list (also OnInitializing call). We probably don't know exact enough how DO does its job at the moment and we would appreciate some more information about that.

Regards Paul Sinnema Diartis AG

Here's our ModelContext class.

using System;
using System.Collections.Generic;
using Diartis.KLIB.KLIBLibrary;
using Xtensive.Storage;
using Xtensive.Storage.Configuration;
using Xtensive.Storage.Model;

namespace Diartis.KLIB.Model
{
    /// <summary>
    /// Singleton. Contains all things of the Model that are common to all Entities. It is implemented as a Singleton because XAML
    /// can't use static classes in an easy manner.
    /// </summary>
    public class ModelContext : IDisposable
    {
        #region Static
        private static readonly object m_Lock = new object();
        private static ModelContext m_ModelContext = null;
        private static bool m_Preload = false;
        private DomainConfiguration m_DomainConfiguration = null;
        private Domain m_Domain = null;
        private Session m_Session = null;
        private bool m_IsSaving;

        /// <summary>
        /// Current version of the DB structure (tables, columns of tables and indexes). This version is counted up if the previous
        /// DB structure is incompatible and an upgrade must be initiated.
        /// </summary>
        public const int StructureVersion = 6;

        /// <summary>
        /// Current version of the DB content of the tables (row data). This version is counted up if the previous DB content
        /// is incompatible and an upgrade must be initiated.
        /// </summary>
        public const int ContentVersion = 0;

        /// <summary>
        /// Setting this value to false will prevent pre loading of tables that are defined as IsCachedTable in the DataTypes.t4
        /// Default = true
        /// </summary>
        public static bool Preload
        {
            get
            {
                return m_Preload;
            }
            set
            {
                m_Preload = value;
            }
        }

        /// <summary>
        /// Gets a Singleton instance of the context (thread safe). ATTENTION: If the instance is not used anymore it MUST be disposed manually
        /// (DataObjects reports a "different thread" problem if the garbage collector disposes the context. This could be fixed in the future.)
        /// This will also open a DataObjects default session ('KLIBSession') which handles the entity changes and saves.
        /// </summary>
        public static ModelContext Instance
        {
            get
            {
                lock (m_Lock)
                {
                    if (m_ModelContext == null)
                    {
                        m_ModelContext = new ModelContext();

                        // The session must be opened immediately, because the DataObject's 'Query' class uses the current session to
                        // execute any SQL commands
                        m_ModelContext.OpenSession();
                    }
                    return m_ModelContext;
                }
            }
        }

        #endregion

        /// <summary>
        /// Only one context can exist which is shared. Use "KLIBContext.Instance" instead.
        /// </summary>
        private ModelContext()
        {
            // Don't put any code here, move it to 'Instance'! One part recursion could occur [ar]
        }

        ~ModelContext()
        {
            Dispose(false);
        }

        /// <summary>
        /// Get the DataObjects Configuration for "KLIBSQLDatabase"
        /// </summary>
        public DomainConfiguration KLIBDomainConfiguration
        {
            get
            {
                if (m_DomainConfiguration == null)
                {
                    m_DomainConfiguration = DomainConfiguration.Load("KLIBSQLDatabase");
                    m_DomainConfiguration.AutoValidation = false;
                }

                return m_DomainConfiguration;
            }
        }

        /// <summary>
        /// Get the main DB domain with all the tables inside. On the first get the domain will be built up.
        /// </summary>
        public Domain KLIBDomain
        {
            get
            {
                try
                {
                    if (m_Domain == null)
                    {
                        m_Domain = Domain.Build(KLIBDomainConfiguration);
                    }
                    return m_Domain;
                }
                catch
                {
                    throw;
                }
            }
        }

        /// <summary>
        /// Opens a new DataObjects Session and makes it the current one ('Session.Current')
        /// </summary>
        private void OpenSession()
        {
            // Open the Session of DataObjects. Will remain open for as long as the Application runs
            m_Session = Session.Open(KLIBDomain);
            // We're using Disconnected IO
            DisconnectedState state = new DisconnectedState();
            // Attach the DisconnectedState to the Session
            state.Attach(m_Session);
            // Allow DataObjects Session to get data from the DB when not found in the Cache
            state.Connect();

            m_Session.EntityChanging += new EventHandler<EntityEventArgs>(SessionEntityChanging);
        }

        /// <summary>
        /// Current DataObjects session that is automatically opened if the 'ModelContext.Instance' is created the first time
        /// </summary>
        public Session KLIBSession
        {
            get { return m_Session; }
        }

        private readonly IList<AbstractEntity> m_ChangedEntities = new List<AbstractEntity>();

        /// <summary>
        /// Is called when any Entity changes. If it is not in the ChangedEntities list it is added
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SessionEntityChanging(object sender, EntityEventArgs e)
        {
            if (e.Entity is AbstractEntity)
            {
                AbstractEntity abstractEntity = (AbstractEntity)e.Entity;

                if (!m_ChangedEntities.Contains(abstractEntity))
                {
                    m_ChangedEntities.Add(abstractEntity);
                }
            }
        }

        /// <summary>
        /// The data was persisted to the DB.
        /// </summary>
        private void OnSaved()
        {
            foreach (var abstractEntity in m_ChangedEntities)
            {
                abstractEntity.OnInitializing(AbstractEntity.EntityInitializationMode.Saved);
            }

            // Clear all saved Entities from the ChangedEntities list
            m_ChangedEntities.Clear();
        }

        /// <summary>
        /// The data is about to be persisted to the DB.
        /// </summary>
        private void OnSaving()
        {
            foreach (var abstractEntity in m_ChangedEntities)
            {
                abstractEntity.OnInitializing(AbstractEntity.EntityInitializationMode.Saving);

                switch (abstractEntity.EntityStateP.Value)
                {
                    case EntityState.CreatedNew:
                    case EntityState.CreatedChanged:
                        abstractEntity.Stamp(EntityStamp.Creation);
                        break;
                    case EntityState.LoadedNew:
                        break;
                    case EntityState.LoadedChanged:
                        abstractEntity.Stamp(EntityStamp.Change);
                        break;
                    case EntityState.Deleted:
                        break;
                    default:
                        break;
                }
            }
        }

        /// <summary>
        /// Validation
        /// </summary>
        /// <returns></returns>
        public bool Validate()
        {
            // TODO: Somehow the Validate() method got lost. Recover its content
            return true;
        }

        /// <summary>
        /// Get the MessageList
        /// </summary>
        public MessageList ValidationErrorList
        {
            get
            {
                // TODO: Somehow the ValidationErrorList got lost. Recover its content
                return null;
            }
        }

        /// <summary>
        /// Save all changes to the DB. Returns 'true' if Validation and Saving was successfully.
        /// TODO: remove the userToken parameter
        /// </summary>
        public bool SaveChanges()
        {
            try
            {
                // Signal that a save is underway
                IsSaving = true;
                // Signal all changed entities that we are about to persist the data to the DB.
                OnSaving();
                // We need to call the ApplyChanges to persist changes in the Cache to the DB.
                // What in fact happens is that DataObjects detaches the DisconnectedState from the Session
                // and replays all the Operations (changes) to the Session.
                // What I (yet) don't know is if the ApplyChanges() below, also call the Persist().
                m_Session.DisconnectedState.ApplyChanges();
                // Reconnect the disconnected state
                m_Session.DisconnectedState.Connect();
                // Signal all changed entities that the data has been persisted to the DB.
                OnSaved();
            }
            finally
            {
                IsSaving = false;
            }

            return true;
        }

        /// <summary>
        /// Is 'SaveChanges' currently in progress? This can be used to exclude some action from running during the save operation.
        /// </summary>
        public bool IsSaving
        {
            get { return m_IsSaving; }
            set { m_IsSaving = value; }
        }

        /// <summary>
        /// Returns a list of all KLIB entity classes
        /// </summary>
        public List<Type> GetAllEntityClasses()
        {
            List<Type> classes = new List<Type>();
            foreach (TypeInfo typeInfo in KLIBDomain.Model.Types.Entities)
            {
                if (typeInfo.Attributes == TypeAttributes.Entity)
                {
                    classes.Add(typeInfo.UnderlyingType);
                }
            }
            return classes;
        }

        #region IDisposable

        private bool m_Disposed;

        public void Dispose()
        {
            Dispose(true);
        }

        public void Dispose(bool dispose)
        {
            if (dispose)
            {
                if (!m_Disposed)
                {
                    m_Session.Dispose();
                    m_Domain.Dispose();
                    m_DomainConfiguration.Dispose();
                    m_Disposed = true;
                }
            }
        }

        #endregion
    }
}

Updated at 08.07.2010 17:53:38

Just thinking out loud:

I've seen the code for the DisconnectedState. I see the concept (partly) but would like tell you how we implemented it.

  • In our ModelContext we open a Configuration, Domain, Session. We attach a DisconnectedState and call the Connect on the state. So far everything is clear to us
  • We read, create, change Entities and then....
  • We call the ApplyChanges() on the State.

I see that the DisconnectedState does a replay of all the Operations on the Session. I guess this also causes objects that were created on the DisconnectedState get created in the Session. Now here's where I get lost. In our Entities the Constructor is called and the OnInitialize(). But when I call the ApplyChanges() both get called again.

How, if at all, should we react in our objects? As you can see in the class above (ModelContext) we've implemented an 'IsSaving' property. We set this just before calling the ApplyChanges() and reset if after the call. In our entities we test this on the ModelContext and don't do the Initialization we did when creating an Entity for the DisconnectedState.

I'm not at all shure if that's how it should work.

Maybe you could tell us the concept behind the DisconnectedState a bit deeper than what's in the PDF?

Regards Paul Sinnema Diartis AG

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

asked Jul 08 '10 at 15:21

Paul%20Sinnema's gravatar image

Paul Sinnema
261878896


One Answer:

Sorry, just read everything, now I will make a set of posts explaining all touched topics.

The most important one seems about DisconnectedState, ApplyChanges and events: 1) Yes, when changes are applied to the same Session, all the events will be raised again here - and that's correct 2) There are Session.DisconnectedState and Session.IsDesconnected properties allowing you to ensure they're handled just once 3) Generally, it's better to avoid applying the changes to the same Session, if UI still uses (i.e. is bound to) the old objects. When we replay entity creation operations, we may associate a new entity with the existing key there, but if you keep reference to the old one, it may become non-functional. Moreover, identifiers are normally remapped during this process, so old entities will enter "removed" state when you'll start using them after connection. In short, always rebind the UI after ApplyChanges.

To be continued.


Concerning the original error:

When you enumerate our enumerables (incl. query result or EntitySet), we ensure auto-transaction IS opened. So the error you see here looks strange.

But there is a consequence you must know about such "auto transactions for enumerables": we use TransactionalExtensions.ToTransactional(...) methods to arrange this. Note that if transaction is outermost, there is no way for us here to find out if we should commit it or roll it back - there is no way for IDisposable.Dispose to know if it is disposing when exception had happened inside a block it is used in (just remembered I wrote about this, see the tail of this post).

So that's why:

  • we never create nested transactions for enumerations of such "transactional" sequences

  • we always commit the outermost transaction we create for enumerations of such sequences.

Returning back to the original error: so is it reproducible?

To be continued.


Now returning back to the DisconnectedState. Besides DisconnectedState itself, there are two parts:

1. Chaining SessionHandler. Being attached, it "passes" all the CRUD operations through DisconnectedState cache, so that:

  • CRUD operations never reach actual SessionHandler

  • Fetch operations look up for Tuple (Entity state) cached in DisconnectedState cache first, and pass the operation through original SessionHandler only if there is no cached Tuple, and DisconnectedState is connected.

  • Query operations are either blocked (if DisconnectedState isn't connected), or passed to the original SessionHandler. If this is happens, state of any materialized entity also gets cached in DisconnectedState cache.

There are some aspects related to transaction handling as well, but let's leave this for now.

2. DisconnectedState cache. This cache is a Dictionary<key,disconnectedentitystate> - like object, but with layered structure allowing us to create savepoints (= support nested transactions) there and rollback to any of them almost instantly (~ in constant time).

DisconnectedEntityState is pretty simple object: it is a triplet of:

  • Key - entity's key

  • Tuple - underlying state of all the columns begind the entity. This is almost always a DifferentialTuple, this is explained below.

  • IsRemoved flag. So DisconnectedState caches info about removed objects you tried to fetch, and, obviously, remembers the objects you removed.

Inside out, cache is based on two primitives:

  • DifferentialDictionary - a dictionary-like object, which internal state is actually a difference between Origin (another Dictionary, frequently - one more DifferentialDictionary) and the state it actually exposes.

  • DifferentialTuple - very similar structure, but for Tuple type.

Based on this, it provides the following characteristics: 1) Resolving entity state always requires ~ constant time, assuming the number of transaction nesting (or the number of active savepoints) is small (let's consider this is always intact further). I.e. in this case it provides performance similar to regular Dictionary. 2) Modifying the state of particular entity also requires constant time. 3) Rolling back to any savepoint requires constant time. In fact, nearly zero: we must just change the reference to the "current" differential dictionary. 4) Committing the transaction requires O(countOfChangedEntities) time, i.e. time proportional to the number of changed entities there - we should merge their state into the lower layer. But since any of these changes already required constant time before (see case 2), we can conclude amortized commit time is constant as well, while entity state change time is still a constant.

So now it's clear why we use such a structure for internal state cache: it provides the same amortized performance as regular Dictionary, but allows us to support nested transactions there. When we rollback a transaction, we actually just switch a pointer + get rid of tail of operation log.

answered Jul 09 '10 at 09:26

Alex%20Yakunin's gravatar image

Alex Yakunin
29714412

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

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×573

Asked: Jul 08 '10 at 15:21

Seen: 4,326 times

Last updated: Jul 08 '10 at 15:21

powered by OSQA