Exemple #1
0
            public void OwnedTypesDoNotNeedToBeIncluded()
            {
                var newBillingAddress = new Address {
                    City = "Krakow", ZipPostCode = "04-218"
                };
                var newDeliveryAddress = new Address {
                    City = "Warsaw", ZipPostCode = "00-001"
                };
                var newOrderInfo = new OrderInfo {
                    BillingAddress = newBillingAddress, DeliveryAddress = newDeliveryAddress, OrderNumber = "#1"
                };

                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringRelationships), GetCallerName());
                var dbCtxOptions       = dbConnectionString
                                         .AsSqlConnectionString <ShopContext>()
                                         .EnsureDb();

                using (var context = dbCtxOptions.BuildDbContext().StartLogging(_testOutput.AsLineWriter()))
                {
                    context.Add(newOrderInfo);
                    context.SaveChanges();
                }

                using (var context = dbCtxOptions.BuildDbContext().StartLogging(_testOutput.AsLineWriter()))
                {
                    var oi =
                        context
                        .OrderInfos
                        .Single();

                    oi.BillingAddress.Should().NotBeNull("because it's an owned type");
                    oi.DeliveryAddress.Should().NotBeNull("because it's also an owned type");
                }
            }
Exemple #2
0
            public void CreatesOneToManyRelationship()
            {
                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringRelationships), GetCallerName());

                using var context =
                          dbConnectionString
                          .AsSqlConnectionString <ManufacturerContext>()
                          .EnsureDb()
                          .BuildDbContext()
                          .StartLogging(_testOutput.AsLineWriter());

                var newUsbs = new[] { new UsbSlot {
                                          UsbVersion = "3.0"
                                      }, new UsbSlot {
                                          UsbVersion = "2.0"
                                      } };
                var newNotebook = new Notebook {
                    Name = "Pear", Usbs = newUsbs
                };

                context.Add(newNotebook);
                context.SaveChanges();

                context
                .Notebooks
                .Include(n => n.Usbs)
                .SingleOrDefault()
                .Should().NotBeNull("because has been successfully added");
            }
Exemple #3
0
            public void CreatesOptionTwoOneToOneRelationship()
            {
                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringRelationships), GetCallerName());

                using var context =
                          dbConnectionString
                          .AsSqlConnectionString <ConventionContext>()
                          .EnsureDb()
                          .BuildDbContext()
                          .StartLogging(_testOutput.AsLineWriter());

                var newAttendee = new Attendee {
                    Name = "John Smith"
                };                        // Attendee can exist without Ticket.

                context.Add(newAttendee); // var newAttendee is now being tracked.
                context.SaveChanges();
                newAttendee.Ticket.Should().BeNull($"because it has not been provided and {nameof(Attendee)} can exist without {nameof(Ticket)}");

                newAttendee.Ticket = new Ticket {
                    Type = "normal"
                };                                                   // Properties Attendee, AttendeeId and TicketId are handled by EF Core.
                context.SaveChanges();

                var nameTicketTypePair =
                    context
                    .Attendees
                    .Include(a => a.Ticket)                     // Now, Include() handles joining in the DB.
                    .Select(a => new { a.Name, a.Ticket.Type }) // Much simpler than the one in OptionOne.
                    .First();

                nameTicketTypePair.Should().BeEquivalentTo(new { Name = "John Smith", Type = "normal" }, "because that's the expected output" +
                                                           " of the above query");
            }
Exemple #4
0
            public void CreatesManyToManyRelationshipByConvention()
            {
                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringRelationships), GetCallerName());

                using var context =
                          dbConnectionString
                          .AsSqlConnectionString <BookStoreContext>()
                          .EnsureDb()
                          .BuildDbContext()
                          .StartLogging(_testOutput.AsLineWriter());

                var aFreemanAuthor = new Author {
                    Name = "Adam Freeman"
                };
                var eEvansAuthor = new Author {
                    Name = "Eric Evans"
                };
                var aspBook = new Book {
                    Title = "...ASP.NET CORE..."
                };
                var dddBook = new Book {
                    Title = "...DDD..."
                };

                context
                .Invoking(ctx =>
                {
                    ctx.AddRange(new[] { aFreemanAuthor, eEvansAuthor });
                    ctx.AddRange(new[] { aspBook, dddBook });
                    ctx.SaveChanges();
                })
                .Should().NotThrow("because it's actually the 'zero-or-one-or-many' relationship.");
                context.Entry(aspBook).State.Should().Be(EntityState.Unchanged, "because it has already been saved and" +
                                                         " has not been modified afterwards");
                aspBook.AuthorLinks.Should().BeNull("because tracking doesn't automatically loads navigation properties");
                context.Entry(aspBook).Collection(a => a.AuthorLinks).Load(); // Load navigation property explicitly.
                context.Entry(aspBook).State.Should().Be(EntityState.Unchanged, "because it's still unchanged - just its property has been loaded");
                aspBook.AuthorLinks.Should().NotBeNull("because already loaded");
                aspBook.AuthorLinks.Count().Should().Be(0, "because no links have been specified");
                aspBook.AuthorLinks = aspBook.AuthorLinks.Append(new BookAuthor {
                    Author = aFreemanAuthor
                }).ToList();
                context.Invoking(ctx => ctx.SaveChanges()).Should().NotThrow("because just Author must be specified in BookAuthor - the rest is" +
                                                                             " handled by EF Core");
                aspBook.AuthorLinks = aspBook.AuthorLinks.Append(new BookAuthor {
                    Author = eEvansAuthor
                }).ToList();
                dddBook.AuthorLinks = new List <BookAuthor> {
                    new BookAuthor {
                        Author = eEvansAuthor
                    }, new BookAuthor {
                        Author = aFreemanAuthor
                    }
                };
                context.SaveChanges();
                context.Set <BookAuthor>().Count().Should().Be(4, "because 2 authors * 2 books");
            }
Exemple #5
0
            public void TablePerHierarchySupportsInheritance()
            {
                var cardPayment = new PaymentCard {
                    Amount = 2000M, Receipt = "ęśąćż"
                };
                var cashPayment = new PaymentCash {
                    Amount = 100M
                };
                var notebookSoldIt = new SoldIt {
                    WhatSold = "Notebook", Payment = cardPayment
                };
                var keyboardSoldIt = new SoldIt {
                    WhatSold = "Keyboard", Payment = cashPayment
                };

                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringRelationships), GetCallerName());
                var dbCtxOptions       = dbConnectionString
                                         .AsSqlConnectionString <ShippingContext>()
                                         .EnsureDb();

                using (var context = dbCtxOptions.BuildDbContext().StartLogging(_testOutput.AsLineWriter()))
                {
                    context.AddRange(new[] { notebookSoldIt, keyboardSoldIt });
                    context.SaveChanges();
                }

                using (var context = dbCtxOptions.BuildDbContext().StartLogging(_testOutput.AsLineWriter()))
                {
                    var notebookPayment =
                        context
                        .SoldIts
                        .Where(si => si.WhatSold == "Notebook")
                        .Select(si => si.Payment)
                        .Single();

                    var keyboardPayment =
                        context
                        .SoldIts
                        .Where(si => si.WhatSold == "Keyboard")
                        .Select(si => si.Payment)
                        .Single();

                    notebookPayment.Should().BeOfType <PaymentCard>("because the original type has been preserved");
                    notebookPayment.Type.Should().Be("card", $"because that's a discriminator value indicating {nameof(PaymentCard)} type");

                    keyboardPayment.Should().BeOfType <PaymentCash>("because the original type has been preserved");
                    keyboardPayment.Type.Should().Be("cash", $"because that's a discriminator value indicating {nameof(PaymentCash)} type");

                    context
                    .Set <Payment>()
                    .OfType <PaymentCard>()
                    .First().Receipt
                    .Should()
                    .Be("ęśąćż", "because that's another way to handle a hierarchical table");
                }
            }
Exemple #6
0
        public QueryingTheDbFixture(ITestOutputHelper testOutput)
        {
            _testOutput         = testOutput;
            _dbConnectionString = DbConnectionString.Create(GetType().Name);
            _fact = DbContextFactoryManager <BookStoreContext> .Instance.GetDbContextFactory(nameof(QueryingTheDbFixture));

            _fact.RegisterOnInit(dbCtxOpts =>
            {
                dbCtxOpts.SeedWith(@"TestData\RawTestData1.json");
            });
            _fact.InitDb(_dbConnectionString);
        }
        public ChangingTheDbContent(ITestOutputHelper testOutput)
        {
            _testOutput = testOutput;
            _fact       = DbContextFactoryManager <BookStoreContext> .Instance.GetDbContextFactory(nameof(ChangingTheDbContent));

            _fact.RegisterOnInit(dbCtxOpts =>
            {
                dbCtxOpts.SeedWith(@"TestData\RawTestData1.json");
            });
            var dbConnectionStrings = ListFactMethodNames().Select(str => DbConnectionString.Create(GetType().Name, str));

            _fact.InitDbAsync(dbConnectionStrings).Wait();
        }
Exemple #8
0
            public void TableIsSplitIntoTwoEntities()
            {
                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringRelationships), GetCallerName());

                using var context =
                          dbConnectionString
                          .AsSqlConnectionString <BookStoreContext>()
                          .EnsureDb()
                          .BuildDbContext()
                          .StartLogging(_testOutput.AsLineWriter());

                var newDetail = new BookDetail {
                    Price = 49M
                };
                var newSummary = new BookSummary {
                    Title = "Entity Framework Core IN ACTION", Details = newDetail
                };

                context.Add(newSummary);
                context.SaveChanges();

                context
                .BookSummaries
                .Single()
                .Title
                .Should().Contain("Entity Framework");

                var aloneSummary = new BookSummary {
                    Title = "C# 8.0 in a Nutshell"
                };

                context.Add(aloneSummary);
                context.Invoking(ctx => ctx.SaveChanges()).Should().NotThrow <Exception>("because not all parts of a split table must be saved at once");

                context.Invoking(ctx =>
                {
                    ctx
                    .BookSummaries
                    .Include(bs => bs.Details)
                    .Where(bs => bs.Title.ToLower().Contains("c#"))
                    .Select(bs => bs.Details.Price)
                    .Single();
                }).Should().NotThrow("because EF Core returns the default values in this case");
            }
Exemple #9
0
            public void CreatesOptionThreeOneToOneRelationship()
            {
                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringRelationships), GetCallerName());

                using var context =
                          dbConnectionString
                          .AsSqlConnectionString <ConventionContext>()
                          .EnsureDb()
                          .BuildDbContext()
                          .StartLogging(_testOutput.AsLineWriter());

                var newAttendee = new Attendee {
                    Name = "John Smith"
                };                        // Attendee can exist without Ticket.

                context.Add(newAttendee); // var newAttendee is now being tracked.
                context.SaveChanges();
                newAttendee.Ticket.Should().BeNull($"because it has not been provided and {nameof(Attendee)} can exist without {nameof(Ticket)}");

                var newAttendeeEntry = context.Entry(newAttendee);

                newAttendeeEntry
                .Invoking(ae => ae.Property($"{nameof(Attendee.Ticket)}{nameof(Ticket.TicketId)}").CurrentValue)
                .Should()
                .Throw <Exception>("because there's no need for a shadow property to determine the relationship by EF Core");

                newAttendee.Ticket = new Ticket {
                    Type = "normal"
                };                                                   // Properties Attendee, AttendeeId and TicketId are handled by EF Core.
                context.SaveChanges();

                var nameTicketTypePair =
                    context
                    .Attendees
                    .Include(a => a.Ticket)
                    .Select(a => new { a.Name, a.Ticket.Type })
                    .First();

                nameTicketTypePair.Should().BeEquivalentTo(new { Name = "John Smith", Type = "normal" }, "because that's the expected output" +
                                                           " of the above query");
            }
            public void DependentEntityContainsPrincipalEntityIdAsTheShadowProperty()
            {
                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringNonrelationalProperties), GetCallerName());

                using var context =
                          dbConnectionString
                          .AsSqlConnectionString <PrincipalDependentContext>()
                          .EnsureDb()
                          .BuildDbContext()
                          .StartLogging(_testOutput.AsLineWriter());

                Func <object> func = () =>
                                     context
                                     .Entry(new Dependent())
                                     .Property($"{nameof(Dependent.NavigationProp)}{nameof(Principal.PrincipalId)}")
                                     .CurrentValue;

                FluentActions
                .Invoking(func)
                .Should()
                .NotThrow($"because EF Core should have created the shadow property representing {nameof(Principal.PrincipalId)} " +
                          $"to be able to link {nameof(Dependent)} to {nameof(Principal)}");
            }
Exemple #11
0
            public void CreatesRelationshipUsingAlternateUniqueKey()
            {
                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringRelationships), GetCallerName());

                using var context =
                          dbConnectionString
                          .AsSqlConnectionString <ContactBookContext>()
                          .EnsureDb()
                          .BuildDbContext()
                          .StartLogging(_testOutput.AsLineWriter());

                var newContact = new ContactInfo {
                    MobileNumber = "1234567890"
                };
                var newPerson = new Person {
                    Name = "John Smith", UserId = "*****@*****.**", Contact = newContact
                };

                context.Add(newPerson);
                context.SaveChanges();
                newContact.EmailAddress.Should().Be(newPerson.UserId, "because it's the foreign key linking to Person by its UserId" +
                                                    " which has already been set by EF Core on SaveChanges()");
            }
Exemple #12
0
            public void CreatesOptionOneOneToOneRelationship()
            {
                var dbConnectionString = DbConnectionString.Create(nameof(ConfiguringRelationships), GetCallerName());

                using var context =
                          dbConnectionString
                          .AsSqlConnectionString <ConventionContext>()
                          .EnsureDb()
                          .BuildDbContext()
                          .StartLogging(_testOutput.AsLineWriter());

                var newTicket = new Ticket {
                    Type = "normal"
                };

                context.Add(newTicket);
                context.SaveChanges();
                newTicket.TicketId.Should().NotBe(0, "because new id has been assigned by the DB");

                var newAttendee = new Attendee {
                    Name = "John Smith", ConventionTicketId = newTicket.TicketId
                };

                context.Add(newAttendee);
                context.SaveChanges();

                // Inner join as an equivalent of EF Core Include() for an entity with no navigation property.
                var nameTicketTypePair =
                    context
                    .Attendees
                    .Join(context.Set <Ticket>(), a => a.ConventionTicketId, t => t.TicketId, (a, t) => new { a.Name, t.Type })
                    .First();

                nameTicketTypePair.Should().BeEquivalentTo(new { Name = "John Smith", Type = "normal" }, "because that's the expected output" +
                                                           " of the above query");
            }
        private BookStoreContext CreateBookStoreContext()
        {
            var dbConnectionString = DbConnectionString.Create(GetType().Name, GetCallerName(1));

            return(_fact.Create(dbConnectionString, _testOutput.AsLineWriter()));
        }