static void Main(string[] args)
        {
            MyUser original = new MyUser(1, "Joe", "Bloggs", "*****@*****.**");
            MyUser changed  = new MyUser(1, "John", "Bloggs", "*****@*****.**", "Line 1", "Line 2", "City", "ZipCode");

            ChangeLogger logger = new ChangeLogger(original.Id, original, changed);

            if (!logger.Success)
            {
                Console.Write(logger.Exception.ToString());
                return;
            }

            // You can also change the value of the changed class before calling Audit
            changed.LastName = "Blogs";

            logger.Audit();
            if (!logger.Success)
            {
                Console.Write(logger.Exception.ToString());
                return;
            }

            foreach (ChangeLog change in logger.Changes)
            {
                Console.Write(string.Format("{2} property changed from {3} to {4} for class {1} with id {0}\r\n", change.ObjectId, change.ObjectType, change.Property, change.ValueOld, change.ValueNew));
            }

            Console.ReadKey();
        }
        public static IChangeLogger CreateChangeLogger(ConnectionFactory.ConnectionMethod connectionMethod, string connectionstring = null,
                                                       DbConnection conn = null, bool?killConnectionOnDispose = null)
        {
            IChangeLogger c = new ChangeLogger();

            switch (connectionMethod)
            {
            case ConnectionFactory.ConnectionMethod.AppSettingsConnectionString:
            {
                c.LoadContext();
                break;
            }

            case ConnectionFactory.ConnectionMethod.ConnectionString:
            {
                c.LoadContext(connectionstring);
                break;
            }

            case ConnectionFactory.ConnectionMethod.CurrentContextConnection:
            {
                bool killconn = false;
                if (killConnectionOnDispose.HasValue)
                {
                    killconn = killConnectionOnDispose.Value;
                }

                c.LoadContext(conn, killconn);
                break;
            }
            }

            return(c);
        }
Ejemplo n.º 3
0
        public void TestSolverRuleOnce()
        {
            var game = (new GameFactoryForTesting()).GenerateGameOneSolution();

            var changesOnce      = new ChangeLogger(true);
            var changesUnlimited = new ChangeLogger(false);
            var fullGridRules    = new List <ISolverRule>()
            {
                changesOnce,
                changesUnlimited
            };

            var solver = new Solver(null, fullGridRules, new BruteForce(), new Backup <IBimaruGrid>());

            solver.Solve(game);

            Assert.IsTrue(changesOnce.NumberOfSolverRuleCalls == 1);
            Assert.IsTrue(changesUnlimited.NumberOfSolverRuleCalls > 1);
        }
Ejemplo n.º 4
0
        private void logChanges(TPrincipal principal)
        {
            var logger = new ChangeLogger <TChangeSet, TPrincipal>(context, factory, filter);

            // This returns the log objects, but they are not attached to the context
            // so the context change tracker hasn't noticed them
            var oven = logger.Log(context.ObjectStateManager);

            // So when we accept changes, we are only accepting the changes from the
            // original changes - the context hasn't yet detected the log changes
            context.AcceptAllChanges();

            // This code then attaches the log objects to the context
            if (oven.HasChangeSet)
            {
                // First do any deferred log value calculations.
                // See PropertyChange.Bake for more information
                TChangeSet changeSet = oven.Bake(DateTime.Now, principal);
                context.AddChangeSet(changeSet);
            }
        }
Ejemplo n.º 5
0
        public void TestInitialFieldChanges()
        {
            var game = (new GameFactory()).GenerateEmptyGame(2, 2);

            game.Grid[new GridPoint(0, 0)] = BimaruValue.WATER;
            game.Grid[new GridPoint(0, 1)] = BimaruValue.WATER;

            var changeLogger = new ChangeLogger();
            var solver       = new Solver(new List <IFieldValueChangedRule>()
            {
                changeLogger
            }, null, null, new Backup <IBimaruGrid>());

            solver.Solve(game);

            AssertEqualChangedEventArgs(
                new List <FieldValueChangedEventArgs <BimaruValue> >()
            {
                new FieldValueChangedEventArgs <BimaruValue>(new GridPoint(0, 0), BimaruValue.UNDETERMINED),
                new FieldValueChangedEventArgs <BimaruValue>(new GridPoint(0, 1), BimaruValue.UNDETERMINED),
            },
                changeLogger);
        }
Ejemplo n.º 6
0
 public Task SaveAndLogAsync(AuditModel audit, Type auditMasterEntityType, string auditMasterEntityId)
 {
     return(ChangeLogger.SaveChangesAsync(_db, _auditDb, _db.SaveChangesWithValidationExplainedAsync, audit, auditMasterEntityType, auditMasterEntityId));
 }
Ejemplo n.º 7
0
        protected async Task <ISaveResult <TChangeSet> > saveChangesAsync(TPrincipal principal, ITransactionProvider transactionProvider, CancellationToken cancellationToken)
        {
            if (!Enabled)
            {
                return(new SaveResult <TChangeSet, TPrincipal>(await context.SaveAndAcceptChangesAsync(cancellationToken: cancellationToken)));
            }

            var result = new SaveResult <TChangeSet, TPrincipal>();

            // We want to split saving and logging into two steps, so that when we
            // generate the log objects the database has already assigned IDs to new
            // objects. Then we can log about them meaningfully. So we wrap it in a
            // transaction so that even though there are two saves, the change is still
            // atomic.
            cancellationToken.ThrowIfCancellationRequested();
            await transactionProvider.InTransactionAsync(async() =>
            {
                var logger = new ChangeLogger <TChangeSet, TPrincipal>(context, factory, filter, serializer);
                var oven   = (IOven <TChangeSet, TPrincipal>)null;

                // First we detect all the changes, but we do not save or accept the changes
                // (i.e. we keep our record of them).
                cancellationToken.ThrowIfCancellationRequested();
                context.DetectChanges();

                // Then we save and accept the changes, which invokes the standard EntityFramework
                // DbContext.SaveChanges(), including any custom user logic the end-user has defined.
                // Eventually, DbContext.InternalContext.ObjectContext.SaveChanges() will be invoked
                // and then the delegate below is called back to prepare the log objects/changes.
                cancellationToken.ThrowIfCancellationRequested();
                result.AffectedObjectCount = await context.SaveAndAcceptChangesAsync(cancellationToken: cancellationToken, onSavingChanges:
                                                                                     (sender, args) =>
                {
                    // This is invoked just moments before EntityFramework accepts the original changes.
                    // Now is our best oppertunity to create the log objects, which will not yet be attached
                    // to the context. They are unattached so that the context change tracker won't noticed
                    // them when accepting the original changes.
                    cancellationToken.ThrowIfCancellationRequested();
                    oven = logger.Log(context.ObjectStateManager);

                    // NOTE: This is the last chance to cancel the save. After this, the original changes
                    //       will have been accepted and it will be too late to stop now (see comment below)
                    cancellationToken.ThrowIfCancellationRequested();
                }
                                                                                     );

                // NOTE: From this point in, we stop honoring the cancellation token.
                //       Why? because if we did, you would end up persisted object changes without any associated logging.
                //       In the interest of data integrity, we either persist the object changes + logging, or nothing at all.

                // If the oven is not set here, then DbContext.SaveChanges() did not call our delegate back
                // when accepting the original changes. Without the oven, we cannot bake the logged changes.
                if (oven == null)
                {
                    throw new ChangesNotDetectedException();
                }

                // Finally, we attach the previously prepared log objects to the context (and save/accept them)
                if (oven.HasChangeSet)
                {
                    // First do any deferred log value calculations.
                    // (see PropertyChange.Bake for more information)
                    // Then detect all the log changes that were previously deferred
                    result.ChangeSet = oven.Bake(DateTime.Now, principal);
                    context.AddChangeSet(result.ChangeSet);
                    context.DetectChanges();

                    // Then we save and accept the changes that result from creating the log objects
                    // NOTE: We do not use SaveAndAcceptChanges() here because we are not interested in going
                    //       through DbContext.SaveChanges() and invoking end-users custom logic.
                    await context.SaveChangesAsync(SaveOptions.AcceptAllChangesAfterSave);
                }
            });

            return(result);
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Run in PreCommit phase to create Framelog module, IOven instance
 /// </summary>
 /// <param name="principal"></param>
 public void LogChanges(TPrincipal principal)
 {
     logger = new ChangeLogger <TChangeSet, TPrincipal>(contextInfo.ObjectContext, factory, filter);
     oven   = logger.Log(contextInfo.ObjectContext.ObjectStateManager);
 }