public void Init()
        {
            var sql = @"drop table posts; drop table blogs; create table blogs ( Id int identity(1,1) not null primary key, BloggerName nvarchar(max), Title nvarchar(max) );
                        create table posts ( Id int identity(1,1) not null primary key, Title nvarchar(max), DateCreated datetime, Content nvarchar(max), BlogId int not null constraint FK_P_B foreign key references Blogs (id) );";

            using (var ctx = new MyAuditedVerboseContext())
            {
                ctx.Database.ExecuteSqlCommand(sql);
            }
        }
        public void Test_EF_Transaction()
        {
            var provider    = new Mock <AuditDataProvider>();
            var auditEvents = new List <AuditEvent>();

            provider.Setup(x => x.InsertEvent(It.IsAny <AuditEvent>())).Returns((AuditEvent ev) =>
            {
                auditEvents.Add(ev);
                return(Guid.NewGuid());
            });
            provider.Setup(p => p.Serialize(It.IsAny <object>())).Returns((object obj) => obj);

            Audit.Core.Configuration.Setup()
            .UseCustomProvider(provider.Object)
            .WithCreationPolicy(EventCreationPolicy.InsertOnEnd)
            .WithAction(x => x.OnScopeCreated(sc =>
            {
                var wcfEvent = sc.Event.GetEntityFrameworkEvent();
                Assert.AreEqual("Blogs", wcfEvent.Database);
            }));

            using (var ctx = new MyAuditedVerboseContext())
            {
                using (var transaction = ctx.Database.BeginTransaction())
                {
                    ctx.Posts.Add(new Post()
                    {
                        BlogId = 1, Content = "other content 1", DateCreated = DateTime.Now, Title = "other title 1"
                    });
                    ctx.SaveChanges();
                    ctx.Posts.Add(new Post()
                    {
                        BlogId = 1, Content = "other content 2", DateCreated = DateTime.Now, Title = "other title 2"
                    });
                    ctx.SaveChanges();
                    transaction.Rollback();
                }
                ctx.Posts.Add(new Post()
                {
                    BlogId = 1, Content = "other content 3", DateCreated = DateTime.Now, Title = "other title 3"
                });
                ctx.SaveChanges();
            }
            var ev1 = (auditEvents[0] as AuditEventEntityFramework).EntityFrameworkEvent;
            var ev2 = (auditEvents[1] as AuditEventEntityFramework).EntityFrameworkEvent;
            var ev3 = (auditEvents[2] as AuditEventEntityFramework).EntityFrameworkEvent;

            Assert.NotNull(ev1.TransactionId);
            Assert.NotNull(ev2.TransactionId);
            Assert.Null(ev3.TransactionId);
            Assert.AreEqual(ev1.TransactionId, ev2.TransactionId);

            Audit.Core.Configuration.ResetCustomActions();
        }
        public void Test_EF_Transaction()
        {
            var provider    = new Mock <AuditDataProvider>();
            var auditEvents = new List <AuditEvent>();

            provider.Setup(x => x.InsertEvent(It.IsAny <AuditEvent>())).Returns((AuditEvent ev) =>
            {
                auditEvents.Add(ev);
                return(Guid.NewGuid());
            });
            provider.Setup(p => p.Serialize(It.IsAny <object>())).Returns((object obj) => obj);

            Audit.Core.Configuration.Setup()
            .UseCustomProvider(provider.Object);

            using (var ctx = new MyAuditedVerboseContext())
            {
                using (var transaction = ctx.Database.BeginTransaction())
                {
                    ctx.Posts.Add(new Post()
                    {
                        BlogId = 1, Content = "other content 1", DateCreated = DateTime.Now, Title = "other title 1"
                    });
                    ctx.SaveChanges();
                    ctx.Posts.Add(new Post()
                    {
                        BlogId = 1, Content = "other content 2", DateCreated = DateTime.Now, Title = "other title 2"
                    });
                    ctx.SaveChanges();
                    transaction.Rollback();
                }
                ctx.Posts.Add(new Post()
                {
                    BlogId = 1, Content = "other content 3", DateCreated = DateTime.Now, Title = "other title 3"
                });
                ctx.SaveChanges();
            }
            var ev1 = (auditEvents[0].CustomFields["EntityFrameworkEvent"] as EntityFrameworkEvent);
            var ev2 = (auditEvents[1].CustomFields["EntityFrameworkEvent"] as EntityFrameworkEvent);
            var ev3 = (auditEvents[2].CustomFields["EntityFrameworkEvent"] as EntityFrameworkEvent);

            Assert.NotNull(ev1.TransactionId);
            Assert.NotNull(ev2.TransactionId);
            Assert.Null(ev3.TransactionId);
            Assert.Equal(ev1.TransactionId, ev2.TransactionId);
        }
        public void Init()
        {
            var sql1 = @"if exists (select * from sysobjects where name = 'posts') drop table posts; if exists (select * from sysobjects where name = 'blogs') drop table blogs; create table blogs ( Id int identity(1,1) not null primary key, BloggerName nvarchar(max), Title nvarchar(max) );
                        create table posts ( Id int identity(1,1) not null primary key, Title nvarchar(max), DateCreated datetime, Content nvarchar(max), BlogId int not null constraint FK_P_B foreign key references Blogs (id) );";
            var sql2 = @"if exists (select * from sysobjects where name = 'child') drop table child; if exists (select * from sysobjects where name = 'parent') drop table parent; CREATE TABLE [Parent] (	Id BIGINT IDENTITY(1,1) NOT NULL, [Name] nvarchar(Max) NOT NULL, CONSTRAINT PK_Parent PRIMARY KEY (Id));
                        CREATE TABLE [Child] ( Id BIGINT IDENTITY(1,1) NOT NULL, [Name] nvarchar(Max) NOT NULL, [Period_Start] datetime NOT NULL, [Period_End] datetime NOT NULL, [ParentId] bigint NOT NULL, CONSTRAINT PK_Child PRIMARY KEY (Id), Constraint FK_Child_Parent Foreign Key ([ParentId]) References Parent(Id));";

            using (var ctx = new MyAuditedVerboseContext())
            {
                ctx.Database.ExecuteSqlCommand(sql1);
            }
            var connectionString = "data source=localhost;initial catalog=ParentChild;integrated security=true;";

            using (var ctx = new ApplicationDbContext(SqlServerDbContextOptionsExtensions.UseSqlServer(new DbContextOptionsBuilder(), connectionString).EnableSensitiveDataLogging().Options))
            {
                ctx.Database.ExecuteSqlCommand(sql2);
            }
        }
        public void Test_EF_Attach()
        {
            EntityFrameworkEvent efEvent = null;

            Audit.Core.Configuration.Setup().UseDynamicProvider(x => x
                                                                .OnInsertAndReplace(ev => {
                efEvent = ev.GetEntityFrameworkEvent();
            }));
            using (var ctx = new MyAuditedVerboseContext())
            {
                var blog = new Blog()
                {
                    Id          = 1,
                    BloggerName = "def-22"
                };
                blog.Title = "Changed-" + Guid.NewGuid();
                ctx.Blogs.Attach(blog);
                ctx.Entry(blog).State = EntityState.Modified;
                ctx.SaveChanges();
            }
            Assert.AreEqual(1, efEvent.Entries.Count);
            Assert.AreEqual("Update", efEvent.Entries[0].Action);
            Assert.IsTrue(efEvent.Entries[0].Changes.Any(ch => ch.ColumnName == "Title"));
        }
        public void Test_EF_Actions(Func <DbContext, int> saveChangesMethod)
        {
            var        provider   = new Mock <AuditDataProvider>();
            AuditEvent auditEvent = null;

            provider.Setup(x => x.InsertEvent(It.IsAny <AuditEvent>())).Returns((AuditEvent ev) =>
            {
                auditEvent = ev;
                return(Guid.NewGuid());
            });
            provider.Setup(p => p.Serialize(It.IsAny <object>())).Returns((object obj) => obj);

            Audit.Core.Configuration.Setup()
            .UseCustomProvider(provider.Object);

            using (var ctx = new MyAuditedVerboseContext())
            {
                ctx.Database.EnsureCreated();
                ctx.Database.ExecuteSqlCommand(@"
delete from AuditPosts
delete from AuditBlogs
delete from Posts
delete from Blogs
SET IDENTITY_INSERT Blogs ON 
insert into Blogs (id, title, bloggername) values (1, 'abc', 'def')
insert into Blogs (id, title, bloggername) values (2, 'ghi', 'jkl')
SET IDENTITY_INSERT Blogs OFF
SET IDENTITY_INSERT Posts ON
insert into Posts (id, title, datecreated, content, blogid) values (1, 'my post 1', GETDATE(), 'this is an example 123', 1)
insert into Posts (id, title, datecreated, content, blogid) values (2, 'my post 2', GETDATE(), 'this is an example 456', 1)
insert into Posts (id, title, datecreated, content, blogid) values (3, 'my post 3', GETDATE(), 'this is an example 789', 1)
insert into Posts (id, title, datecreated, content, blogid) values (4, 'my post 4', GETDATE(), 'this is an example 987', 2)
insert into Posts (id, title, datecreated, content, blogid) values (5, 'my post 5', GETDATE(), 'this is an example 000', 2)
SET IDENTITY_INSERT Posts OFF
                    ");

                var postsblog1 = ctx.Blogs.Include(x => x.Posts)
                                 .FirstOrDefault(x => x.Id == 1);
                postsblog1.BloggerName += "-22";

                ctx.Posts.Add(new Post()
                {
                    BlogId = 1, Content = "content", DateCreated = DateTime.Now, Title = "title"
                });

                var ch1 = ctx.Posts.FirstOrDefault(x => x.Id == 1);
                ch1.Content += "-code";

                var pr = ctx.Posts.FirstOrDefault(x => x.Id == 5);
                ctx.Remove(pr);

                int result = saveChangesMethod.Invoke(ctx);

                var efEvent = auditEvent.CustomFields["EntityFrameworkEvent"] as EntityFrameworkEvent;

                Assert.Equal(4, result);
                Assert.Equal("Blogs" + "_" + ctx.GetType().Name, auditEvent.EventType);
                Assert.True(efEvent.Entries.Any(e => e.Action == "Insert" && (e.Entity as Post)?.Title == "title"));
                Assert.True(efEvent.Entries.Any(e => e.Action == "Insert" && e.ColumnValues["Title"].Equals("title") && (e.Entity as Post)?.Title == "title"));
                Assert.True(efEvent.Entries.Any(e => e.Action == "Update" && (e.Entity as Blog)?.Id == 1 && e.Changes[0].ColumnName == "BloggerName"));
                Assert.True(efEvent.Entries.Any(e => e.Action == "Delete" && (e.Entity as Post)?.Id == 5));
                Assert.True(efEvent.Entries.Any(e => e.Action == "Delete" && e.ColumnValues["Id"].Equals(5) && (e.Entity as Post)?.Id == 5));
                provider.Verify(p => p.InsertEvent(It.IsAny <AuditEvent>()), Times.Once);
            }
        }