public void TestLoadByRoleDbShowQuery()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                context.AddTestEmployeesToDb();
            }
            using (var context = new Chapter06Context(options))
            {
                //ATTEMPT
                var query = context.Employees
                            .Include(x => x.WorksForMe)
                            .Where(x => x.WhatTheyDo.HasFlag(Roles.Development));
                var devDept = query.ToList();

                //VERIFY
                _output.WriteLine(query.ToQueryString());
                devDept.Count.ShouldEqual(7);
                var cto = devDept.Single(x => x.Manager == null);
                cto.ShowHierarchical(s => _output.WriteLine(s));
            }
        }
        public void TestLoadByRoleDb()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                context.AddTestEmployeesToDb();
            }
            using (var context = new Chapter06Context(options))
            {
                //ATTEMPT
                var devDept = context.Employees                                    //#A
                              .Include(x => x.WorksForMe)                          //#B
                              .Where(x => x.WhatTheyDo.HasFlag(Roles.Development)) //#C
                              .ToList();

                /********************************************************
                 #A The database holds all the Employees
                 #B One Include is all that you need - relational fixup will work out what is linked to what
                 #C This filters the employees down to ones that work in Development
                 **********************************************/

                //VERIFY
                devDept.Count.ShouldEqual(7);
            }
        }
Example #3
0
        public void TestDetachAllTrackedEntities(int numCollection)
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                var entityToDetach = context.AddManyTopWithRelationsToDb();
                //ATTEMPT
                using (new TimeThings(_output, $"detach all tracked entities - {numCollection * 3:n0} tracked entities."))
                {
                    foreach (var entityEntry in context.ChangeTracker.Entries()) //#A
                    {
                        if (entityEntry.Entity != null)                          //#B
                        {
                            entityEntry.State = EntityState.Detached;            //#C
                        }
                    }

                    /********************************************
                     #A This will iterate through each tracked EntityEntry in the current DbContext instance
                     #B This filters out tracked entities where the entity class instance has been set to null
                     #C This sets the state of the EntityEntry to Detached
                     **********************************************/
                }

                //VERIFY
                var topEntity = context.Entry(entityToDetach);
                entityToDetach.Collection1.All(x => context.Entry(x).State == EntityState.Detached).ShouldBeTrue();
                entityToDetach.Collection2.All(x => context.Entry(x).State == EntityState.Detached).ShouldBeTrue();
                entityToDetach.Collection3.All(x => context.Entry(x).State == EntityState.Detached).ShouldBeTrue();
            }
        }
        public void TestThenIncludeWorksForMe()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                context.AddTestEmployeesToDb();
            }
            using (var context = new Chapter06Context(options))
            {
                //ATTEMPT
                var all = context.Employees
                          .Include(x => x.WorksForMe)
                          .ThenInclude(x => x.WorksForMe)
                          .ToList();

                //VERIFY
                all.Count.ShouldEqual(11);
                all.Count(x => x.Manager != null).ShouldEqual(10);
                all.Count(x => x.WorksForMe.Any()).ShouldEqual(5);
                var top = all.Single(x => x.Manager == null);
                top.ShowHierarchical(s => _output.WriteLine(s));
            }
        }
Example #5
0
        public void TestLoadWorksForMeAsNoTrackingWithIdentityResolution()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using var context = new Chapter06Context(options);
            context.Database.EnsureCreated();
            context.AddTestEmployeesToDb();

            context.ChangeTracker.Clear();

            //ATTEMPT
            var all = context.Employees
                      .AsNoTrackingWithIdentityResolution()
                      .Include(x => x.WorksForMe)
                      .ToList();

            //VERIFY
            all.Count.ShouldEqual(11);
            all.Count(x => x.Manager != null).ShouldEqual(10);
            all.Count(x => x.WorksForMe.Any()).ShouldEqual(5);
            var top = all.Single(x => x.Manager == null);

            top.ShowHierarchical(s => _output.WriteLine(s));
        }
Example #6
0
        public void TestDeletePrincipal()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using var context = new Chapter06Context(options);
            context.Database.EnsureCreated();
            context.Add(new OnePrincipal {
                Link = new OneDependent()
            });
            context.SaveChanges();

            context.ChangeTracker.Clear();

            //ATTEMPT
            var depToRemove = new OnePrincipal {
                Id = 1
            };

            context.Remove(depToRemove);
            context.SaveChanges();

            //VERIFY
            context.OneDependents.Count().ShouldEqual(0);
            context.OnePrincipals.Count().ShouldEqual(0);
        }
        public void TestBookQueryWithSeparateIncludes()
        {
            //SETUP
            var showlog = false;
            var options = SqliteInMemory.CreateOptionsWithLogging <Chapter06Context>(log =>
            {
                if (showlog)
                {
                    _output.WriteLine(log.Message);
                }
            });

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                context.AddManyTopWithRelationsToDb();
            }
            using (var context = new Chapter06Context(options))
            {
                //ATTEMPT
                var     dummy1 = context.ManyTops.ToList();
                var     dummy2 = context.ManyTops.ToList();
                ManyTop result;
                using (new TimeThings(_output, "sync load - first time"))
                {
                    result = context.ManyTops.Single();                     //#A
                    var a = context.Set <Many1>()                           //#B
                            .Where(x => x.ManyTopId == result.Id).ToList(); //#B
                    var b = context.Set <Many2>()                           //#B
                            .Where(x => x.ManyTopId == result.Id).ToList(); //#B
                    var c = context.Set <Many3>()                           //#B
                            .Where(x => x.ManyTopId == result.Id).ToList(); //#B

                    /*********************************************************
                     #A This read in the main entity class, ManyTop that the relationships link to first
                     #B Then you read in the collections one by one. Relational fixup will fill in the navigational properties in the main entity class, ManyTop
                     **********************************************************/
                }
                using (new TimeThings(_output, "sync load - second time"))
                {
                    result = context.ManyTops.Single();
                    var loadRels = new
                    {
                        a = context.Set <Many1>().Where(x => x.ManyTopId == result.Id).ToList(),
                        b = context.Set <Many2>().Where(x => x.ManyTopId == result.Id).ToList(),
                        c = context.Set <Many3>().Where(x => x.ManyTopId == result.Id).ToList(),
                    };
                }

                //VERIFY
                result.Collection1.Count.ShouldEqual(100);
                result.Collection2.Count.ShouldEqual(100);
                result.Collection3.Count.ShouldEqual(100);
            }
        }
        public void TestBookQueryWithSeparateIncludes()
        {
            //SETUP
            var showlog = false;
            var options = SqliteInMemory.CreateOptionsWithLogging <Chapter06Context>(log =>
            {
                if (showlog)
                {
                    _output.WriteLine(log.Message);
                }
            });

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                context.AddManyTopWithRelationsToDb();
            }
            using (var context = new Chapter06Context(options))
            {
                //ATTEMPT
                var     dummy1 = context.ManyTops.ToList();
                var     dummy2 = context.ManyTops.ToList();
                ManyTop result;
                var     id = 1;
                using (new TimeThings(_output, "sync load - first time"))
                {
                    result = context.ManyTops
                             .AsSplitQuery() //#A
                             .Include(x => x.Collection1)
                             .Include(x => x.Collection2)
                             .Include(x => x.Collection3)
                             .Single(x => x.Id == id);

                    /*********************************************************
                     #A This will cause each Include to be loaded separately, thus stopping the multiplication problem
                     **********************************************************/
                }
                using (new TimeThings(_output, "sync load - second time"))
                {
                    result = context.ManyTops
                             .AsSplitQuery()
                             .Include(x => x.Collection1)
                             .Include(x => x.Collection2)
                             .Include(x => x.Collection3)
                             .Single();
                }

                //VERIFY
                result.Collection1.Count.ShouldEqual(100);
                result.Collection2.Count.ShouldEqual(100);
                result.Collection3.Count.ShouldEqual(100);
            }
        }
Example #9
0
        public void TestAddTestEmployeesToDb()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using var context = new Chapter06Context(options);
            context.Database.EnsureCreated();

            //ATTEMPT
            context.AddTestEmployeesToDb();

            //VERIFY
            context.Employees.Count().ShouldEqual(11);
        }
        public async Task TestBookQueryWithSeparateIncludesAsync()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                context.AddManyTopWithRelationsToDb();
            }
            using (var context = new Chapter06Context(options))
            {
                //ATTEMPT
                var     dummy1 = context.ManyTops.ToList();
                var     dummy2 = context.ManyTops.ToList();
                ManyTop result;
                using (new TimeThings(_output, "async load - first time"))
                {
                    result = await context.ManyTops
                             .AsSplitQuery()
                             .Include(x => x.Collection1)
                             .Include(x => x.Collection2)
                             .Include(x => x.Collection3)
                             .SingleAsync();

                    /*********************************************************
                     #A This read in the main entity class, ManyTop that the relationships link to first
                     #B Then you read in the collections one by one. Relational fixup will fill in the navigational properties in the main entity class, ManyTop
                     **********************************************************/
                }
                using (new TimeThings(_output, "async load - second time"))
                {
                    result = await context.ManyTops
                             .AsSplitQuery()
                             .Include(x => x.Collection1)
                             .Include(x => x.Collection2)
                             .Include(x => x.Collection3)
                             .SingleAsync();
                }

                //VERIFY
                result.Collection1.Count.ShouldEqual(100);
                result.Collection2.Count.ShouldEqual(100);
                result.Collection3.Count.ShouldEqual(100);
            }
        }
Example #11
0
        public void TestLoadManager()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using var context = new Chapter06Context(options);
            context.Database.EnsureCreated();
            context.AddTestEmployeesToDb();

            context.ChangeTracker.Clear();

            //ATTEMPT
            var all = context.Employees.Include(x => x.Manager)
                      .ToList();

            //VERIFY
            all.Count.ShouldEqual(11);
            all.Count(x => x.Manager != null).ShouldEqual(10);
            all.Count(x => x.WorksForMe != null).ShouldEqual(5);
            all.Count(x => x.WorksForMe == null).ShouldEqual(6);
        }
        public void TestDetachAllTrackedEntities(int numCollection)
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                var entityToDetach = context.AddManyTopWithRelationsToDb();
                //ATTEMPT
                using (new TimeThings(_output, $"detach all tracked entities - {numCollection * 3:n0} tracked entities."))
                {
                    context.ChangeTracker.Clear();
                }

                //VERIFY
                var topEntity = context.Entry(entityToDetach);
                entityToDetach.Collection1.All(x => context.Entry(x).State == EntityState.Detached).ShouldBeTrue();
                entityToDetach.Collection2.All(x => context.Entry(x).State == EntityState.Detached).ShouldBeTrue();
                entityToDetach.Collection3.All(x => context.Entry(x).State == EntityState.Detached).ShouldBeTrue();
            }
        }
        public void TestDetachViaCreatingNewDbContext(int numCollection)
        {
            //SETUP
            ManyTop entityToDetach;
            var     options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                entityToDetach = context.AddManyTopWithRelationsToDb(numCollection);
            }
            //ATTEMPT
            using (new TimeThings(_output, $"detach by creating new DbContext - {numCollection * 3:n0} tracked entities."))
            {
                using (var context = new Chapter06Context(options))
                {
                    context.Database.EnsureCreated();
                }
            }

            //VERIFY
        }
        public void TestBookQueryWithNormalIncludes()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                context.AddManyTopWithRelationsToDb();
            }
            using (var context = new Chapter06Context(options))
            {
                //ATTEMPT
                var     dummy1 = context.ManyTops.ToList();
                var     dummy2 = context.ManyTops.ToList();
                ManyTop result;
                using (new TimeThings(_output, "normal includes - first time"))
                {
                    result = context.ManyTops
                             .Include(x => x.Collection1)
                             .Include(x => x.Collection2)
                             .Include(x => x.Collection3)
                             .Single();
                }
                using (new TimeThings(_output, "normal includes - second time"))
                {
                    result = context.ManyTops
                             .Include(x => x.Collection1)
                             .Include(x => x.Collection2)
                             .Include(x => x.Collection3)
                             .Single();
                }

                //VERIFY
                result.Collection1.Count.ShouldEqual(100);
                result.Collection2.Count.ShouldEqual(100);
                result.Collection3.Count.ShouldEqual(100);
            }
        }
        public void TestCostOfNotDetaching(int numCollection)
        {
            //SETUP
            ManyTop entityToDetach;
            var     options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();

                //ATTEMPT
                using (new TimeThings(_output, "SaveChanges - no tracked entities."))
                {
                    context.SaveChanges();
                }
                using (new TimeThings(_output, "SaveChanges - no tracked entities."))
                {
                    context.SaveChanges();
                }

                entityToDetach = context.AddManyTopWithRelationsToDb(numCollection);
                var numEntities = entityToDetach.Collection1.Count +
                                  entityToDetach.Collection2.Count +
                                  entityToDetach.Collection3.Count;


                using (new TimeThings(_output, $"SaveChanges - {numEntities:n0} tracked entities."))
                {
                    context.SaveChanges();
                }
                using (new TimeThings(_output, $"SaveChanges - {numEntities:n0} tracked entities."))
                {
                    context.SaveChanges();
                }
            }

            //VERIFY
        }
Example #16
0
        public void ExampleDetachViaCreatingNewDbContext()
        {
            //SETUP

            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            options.StopNextDispose();
            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                context.AddManyTopWithRelationsToDb();
            }

            //ATTEMPT
            ManyTop entityToDetach;                                   //#A

            using (var tempContext = new Chapter06Context(options))   //#B
            {
                entityToDetach = tempContext.ManyTops.Single();       //#C
                var a = tempContext.Set <Many1>()                     //#D
                        .Where(x => x.ManyTopId == entityToDetach.Id) //#D
                        .ToList();                                    //#D
                //... rest of loads left out to shorten the example
            }                                                         //#E
            //… further code that uses the entityToDetach variable  //#F

            /************************************************************************
             #A This is the variable which will hold the detached entity class with its relationships that were read in separately
             #B Create a new instance of the application's DbContext. This must be done manually because you should not dispose of an instance that has been created by dependency injections
             #C Read of the top level entity class
             #D Read of the Many1 instances. Relational fixup will fill in the navigational collection in the ManyTop class which holds the loaded Many1 instances
             #E The closing of the using block means that the tempContext is disposed, including all ist tracking data
             #F As this point all the entity class instances read in while in the using block are detached from any DbContext
             * ********************************/

            //VERIFY
            entityToDetach.Collection1.Count.ShouldEqual(100);
        }
        public void TestMissingIncludeNotSafeOk()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using var context = new Chapter06Context(options);
            context.Database.EnsureCreated();
            var bookSetup = new BookNotSafe();

            bookSetup.Reviews.Add(new ReviewNotSafe());
            context.Add(bookSetup);
            context.SaveChanges();

            context.ChangeTracker.Clear();

            //ATTEMPT
            var book = context.Books //#A
                                     //... missing Include(x => x.Reviews) //#B
                       .First(x => x.Reviews.Any());

            //VERIFY
            book.Reviews.ShouldNotBeNull();
        }
        public void TestLoadWorksForMeNoWorkingAsNoTracking()
        {
            //SETUP
            var options = SqliteInMemory.CreateOptions <Chapter06Context>();

            using (var context = new Chapter06Context(options))
            {
                context.Database.EnsureCreated();
                context.AddTestEmployeesToDb();
            }
            using (var context = new Chapter06Context(options))
            {
                //ATTEMPT
                var all = context.Employees
                          .AsNoTracking()
                          .Include(x => x.WorksForMe)
                          .ToList();

                //VERIFY
                all.Count.ShouldEqual(11);
                all.Count(x => x.Manager == null).ShouldEqual(11);
                all.Count(x => x.WorksForMe.Any()).ShouldEqual(5);
            }
        }