public IEnumerable <T> ExecuteDelete <T>(
            IExecutionPlan <IEnumerable <T> > plan,
            IExecutionContext context)
            where T : class
        {
            var helper         = new ExecutionHelper(this.Database);
            var table          = this.Database.Tables.FindTable <T>();
            var cascadedTables = helper.GetCascadedTables(table);
            var allTables      = cascadedTables.Concat(new[] { table }).ToArray();

            // Find relations
            // Do not add referred relations!
            RelationGroup allRelations =
                helper.FindRelations(allTables.SelectMany(x => x.Indexes), referred: false);

            this.AcquireWriteLock(table, context);

            var storedEntities = this.Query(plan, table, context);

            this.AcquireWriteLock(cascadedTables, context);
            this.LockRelatedTables(allRelations, context, except: allTables);

            using (AtomicLogScope log = this.StartAtomicLogOperation(context))
            {
                IDeletePrimitive primitive = new DeletePrimitive(this.Database, log);

                primitive.Delete(storedEntities);

                log.Complete();
            }

            return(storedEntities.ToArray());
        }
        public void ExecuteInsert <T>(T entity, IExecutionContext context)
            where T : class
        {
            var helper = new ExecutionHelper(this.Database);
            var table  = this.Database.Tables.FindTable <T>();

            table.Contraints.Apply(entity, context);

            // Find referred relations
            // Do not add referring relations!
            RelationGroup relations = helper.FindRelations(table.Indexes, referring: false);

            // Acquire locks
            this.AcquireWriteLock(table, context);
            this.LockRelatedTables(relations, context, table);

            try
            {
                // Validate the inserted record
                helper.ValidateForeignKeys(relations.Referred, new[] { entity });

                using (AtomicLogScope logScope = this.StartAtomicLogOperation(context))
                {
                    foreach (IIndex <T> index in table.Indexes)
                    {
                        index.Insert(entity);
                        logScope.Log.WriteIndexInsert(index, entity);
                    }

                    logScope.Complete();
                }
            }
            finally
            {
                this.ReleaseWriteLock(table, context);
            }
        }
        public IEnumerable <T> ExecuteUpdater <T>(
            IExecutionPlan <IEnumerable <T> > plan,
            IUpdater <T> updater,
            IExecutionContext context)
            where T : class
        {
            var helper = new ExecutionHelper(this.Database);
            var table  = this.Database.Tables.FindTable <T>();
            var cloner = EntityPropertyCloner <T> .Instance;

            // Determine which indexes are affected by the change
            // If the key of an index containes a changed property, it is affected
            IList <IIndex <T> > affectedIndexes =
                helper.FindAffectedIndexes(table, updater.Changes);

            // Find relations
            // Add both referring and referred relations!
            RelationGroup relations = helper.FindRelations(affectedIndexes);

            this.AcquireWriteLock(table, context);

            var storedEntities = Query(plan, table, context);

            // Lock related tables (based on found relations)
            this.LockRelatedTables(relations, context, table);

            // Find the entities referring the entities that are about to be updated
            var referringEntities =
                helper.FindReferringEntities(storedEntities, relations.Referring);

            using (AtomicLogScope logScope = this.StartAtomicLogOperation(context))
            {
                // Delete invalid index records (keys are invalid)
                for (int i = 0; i < storedEntities.Count; i++)
                {
                    T storedEntity = storedEntities[i];

                    foreach (IIndex <T> index in affectedIndexes)
                    {
                        index.Delete(storedEntity);
                        logScope.Log.WriteIndexDelete(index, storedEntity);
                    }
                }

                // Modify entity properties
                for (int i = 0; i < storedEntities.Count; i++)
                {
                    T storedEntity = storedEntities[i];

                    // Create backup
                    T backup = Activator.CreateInstance <T>();
                    cloner.Clone(storedEntity, backup);
                    T newEntity = updater.Update(storedEntity);

                    // Apply contraints on the entity
                    table.Contraints.Apply(newEntity, context);

                    // Update entity
                    cloner.Clone(newEntity, storedEntity);
                    logScope.Log.WriteEntityUpdate(cloner, storedEntity, backup);
                }

                // Insert to indexes the entities were removed from
                for (int i = 0; i < storedEntities.Count; i++)
                {
                    T storedEntity = storedEntities[i];

                    foreach (IIndex <T> index in affectedIndexes)
                    {
                        index.Insert(storedEntity);
                        logScope.Log.WriteIndexInsert(index, storedEntity);
                    }
                }

                // Validate the updated entities
                helper.ValidateForeignKeys(relations.Referred, storedEntities);

                // Validate the entities that were referring to the old version of entities
                helper.ValidateForeignKeys(relations.Referring, referringEntities);

                logScope.Complete();
            }

            return(storedEntities);
        }
Example #4
0
 public DeletePrimitive(IDatabase database, AtomicLogScope log)
 {
     this.database = database;
     this.log      = log;
 }