// IDisposable implementation /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { if (isDisposed) { return; } try { OrmLog.Debug(Strings.LogSessionXDisposing, this); SystemEvents.NotifyDisposing(); Events.NotifyDisposing(); Services.DisposeSafely(); Handler.DisposeSafely(); CommandProcessorContextProvider.DisposeSafely(); Domain.ReleaseSingleConnection(); disposableSet.DisposeSafely(); disposableSet = null; EntityChangeRegistry.Clear(); EntitySetChangeRegistry.Clear(); EntityStateCache.Clear(); ReferenceFieldsChangesRegistry.Clear(); NonPairedReferencesRegistry.Clear(); } finally { isDisposed = true; } }
// Constructors internal Session(Domain domain, SessionConfiguration configuration, bool activate) : base(domain) { Guid = Guid.NewGuid(); IsDebugEventLoggingEnabled = OrmLog.IsLogged(LogLevel.Debug); // Just to cache this value // Both Domain and Configuration are valid references here; // Configuration is already locked Configuration = configuration; Name = configuration.Name; identifier = Interlocked.Increment(ref lastUsedIdentifier); CommandTimeout = configuration.DefaultCommandTimeout; allowSwitching = configuration.Supports(SessionOptions.AllowSwitching); // Handlers Handlers = domain.Handlers; Handler = CreateSessionHandler(); // Caches, registry EntityStateCache = CreateSessionCache(configuration); EntityChangeRegistry = new EntityChangeRegistry(this); EntitySetChangeRegistry = new EntitySetChangeRegistry(this); ReferenceFieldsChangesRegistry = new ReferenceFieldsChangesRegistry(this); entitySetsWithInvalidState = new HashSet <EntitySetBase>(); // Events EntityEvents = new EntityEventBroker(); Events = new SessionEventAccessor(this, false); SystemEvents = new SessionEventAccessor(this, true); // Etc. PairSyncManager = new SyncManager(this); RemovalProcessor = new RemovalProcessor(this); pinner = new Pinner(this); Operations = new OperationRegistry(this); NonPairedReferencesRegistry = new NonPairedReferenceChangesRegistry(this); CommandProcessorContextProvider = new CommandProcessorContextProvider(this); // Validation context ValidationContext = Configuration.Supports(SessionOptions.ValidateEntities) ? (ValidationContext) new RealValidationContext() : new VoidValidationContext(); // Creating Services Services = CreateServices(); disposableSet = new DisposableSet(); remapper = new KeyRemapper(this); disableAutoSaveChanges = !configuration.Supports(SessionOptions.AutoSaveChanges); // Perform activation if (activate) { ActivateInternally(); } // Query endpoint SystemQuery = Query = new QueryEndpoint(new QueryProvider(this)); }
internal void RollbackTransaction(Transaction transaction) { try { OrmLog.Debug(Strings.LogSessionXRollingBackTransaction, this); SystemEvents.NotifyTransactionRollbacking(transaction); Events.NotifyTransactionRollbacking(transaction); } finally { try { Handler.CompletingTransaction(transaction); } finally { try { if (Configuration.Supports(SessionOptions.SuppressRollbackExceptions)) { RollbackWithSuppression(transaction); } else { Rollback(transaction); } } finally { if (!persistingIsFailed || !Configuration.Supports(SessionOptions.NonTransactionalReads)) { CancelEntitySetsChanges(); ClearChangeRegistry(); NonPairedReferencesRegistry.Clear(); EntitySetChangeRegistry.Clear(); } persistingIsFailed = false; } } } }
private void ProcessChangesOfEntitySets(Action <EntitySetState> action) { var itemsToProcess = EntitySetChangeRegistry.GetItems(); foreach (var entitySet in itemsToProcess) { action.Invoke(entitySet); } }
internal async ValueTask RollbackTransaction(Transaction transaction, bool isAsync) { try { if (IsDebugEventLoggingEnabled) { OrmLog.Debug(Strings.LogSessionXRollingBackTransaction, this); } SystemEvents.NotifyTransactionRollbacking(transaction); Events.NotifyTransactionRollbacking(transaction); } finally { try { Handler.CompletingTransaction(transaction); } finally { try { if (Configuration.Supports(SessionOptions.SuppressRollbackExceptions)) { await RollbackWithSuppression(transaction, isAsync).ConfigureAwait(false); } else { if (isAsync) { await RollbackAsync(transaction).ConfigureAwait(false); } else { Rollback(transaction); } } } finally { if (!persistingIsFailed || !Configuration.Supports(SessionOptions.NonTransactionalReads)) { CancelEntitySetsChanges(); ClearChangeRegistry(); NonPairedReferencesRegistry.Clear(); EntitySetChangeRegistry.Clear(); } persistingIsFailed = false; } } } }
private async ValueTask DisposeImpl(bool isAsync) { if (isDisposed) { return; } sessionLifetimeToken.Expire(); try { if (IsDebugEventLoggingEnabled) { OrmLog.Debug(Strings.LogSessionXDisposing, this); } SystemEvents.NotifyDisposing(); Events.NotifyDisposing(); Services.DisposeSafely(); if (isAsync) { await Handler.DisposeSafelyAsync().ConfigureAwait(false); } else { Handler.DisposeSafely(); } CommandProcessorContextProvider.DisposeSafely(); Domain.ReleaseSingleConnection(); disposableSet.DisposeSafely(); disposableSet = null; EntityChangeRegistry.Clear(); EntitySetChangeRegistry.Clear(); EntityStateCache.Clear(); ReferenceFieldsChangesRegistry.Clear(); NonPairedReferencesRegistry.Clear(); Extensions.Clear(); } finally { isDisposed = true; } }
internal void Persist(PersistReason reason) { EnsureNotDisposed(); if (IsPersisting || EntityChangeRegistry.Count == 0) { return; } EnsureAllAsyncQueriesFinished(); var performPinning = pinner.RootCount > 0; if (performPinning || (disableAutoSaveChanges && !Configuration.Supports(SessionOptions.NonTransactionalEntityStates))) { switch (reason) { case PersistReason.NestedTransaction: case PersistReason.Commit: throw new InvalidOperationException(Strings.ExCanNotPersistThereArePinnedEntities); } } if (disableAutoSaveChanges && reason != PersistReason.Manual) { return; } using (var ts = OpenTransaction(TransactionOpenMode.Default, IsolationLevel.Unspecified, false)) { IsPersisting = true; persistingIsFailed = false; SystemEvents.NotifyPersisting(); Events.NotifyPersisting(); try { using (this.OpenSystemLogicOnlyRegion()) { DemandTransaction(); if (IsDebugEventLoggingEnabled) { OrmLog.Debug(Strings.LogSessionXPersistingReasonY, this, reason); } EntityChangeRegistry itemsToPersist; if (performPinning) { pinner.Process(EntityChangeRegistry); itemsToPersist = pinner.PersistableItems; } else { itemsToPersist = EntityChangeRegistry; } if (LazyKeyGenerationIsEnabled) { RemapEntityKeys(remapper.Remap(itemsToPersist)); } ApplyEntitySetsChanges(); var persistIsSuccessfull = false; try { Handler.Persist(itemsToPersist, reason == PersistReason.Query); persistIsSuccessfull = true; } catch (Exception) { persistingIsFailed = true; RollbackChangesOfEntitySets(); RestoreEntityChangesAfterPersistFailed(); throw; } finally { if (persistIsSuccessfull || !Configuration.Supports(SessionOptions.NonTransactionalEntityStates)) { DropDifferenceBackup(); foreach (var item in itemsToPersist.GetItems(PersistenceState.New)) { item.PersistenceState = PersistenceState.Synchronized; } foreach (var item in itemsToPersist.GetItems(PersistenceState.Modified)) { item.PersistenceState = PersistenceState.Synchronized; } foreach (var item in itemsToPersist.GetItems(PersistenceState.Removed)) { item.Update(null); } if (performPinning) { EntityChangeRegistry = pinner.PinnedItems; pinner.Reset(); } else { EntityChangeRegistry.Clear(); } EntitySetChangeRegistry.Clear(); NonPairedReferencesRegistry.Clear(); } if (IsDebugEventLoggingEnabled) { OrmLog.Debug(Strings.LogSessionXPersistCompleted, this); } } } SystemEvents.NotifyPersisted(); Events.NotifyPersisted(); } finally { IsPersisting = false; } } }