Giter Site home page Giter Site logo

jonpsmith / efcoreinaction-secondedition Goto Github PK

View Code? Open in Web Editor NEW
375.0 375.0 151.0 2.62 MB

Supporting repo to go with book "Entity Framework Core in Action", second edition

Home Page: https://bit.ly/EfCoreBook2

License: MIT License

C# 92.90% HTML 4.23% CSS 0.40% JavaScript 2.47%
asp-net-core database entity-framework netcore

efcoreinaction-secondedition's People

Contributors

jonpsmith avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

efcoreinaction-secondedition's Issues

Get exception when trying to run 'MyFirstEfCoreApp' the second time

I cloned the part 1 project and ran the 'MyFirstEfCoreApp' project. It created the database and created the console window. All of the switch options worked. I wanted to walk through the code so I deleted the database 'MyFirstEfCoreDb' found in "C:\Users\Owner". When I rerun the 'MyFirstEfCoreApp' project I get an exception from
db.Database.EnsureCreated();
Message=Database 'MyFirstEfCoreDb' already exists. Choose a different database name. Source=Core Microsoft SqlClient Data Provider
I've tried several Stack Overflow suggestions to delete the database. None have worked and I've cannot find the database. What am I missing?

Unable to run BookApp

When I run the BookApp project I get the following stack trace:

An error occurred while starting the application.
AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: BizDbAccess.Orders.IPlaceOrderDbAccess Lifetime: Transient ImplementationType: BizDbAccess.Orders.PlaceOrderDbAccess': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.GenericInterfaces.IBizAction`2[BizLogic.Orders.PlaceOrderInDto,DataLayer.EfClasses.Order] Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderAction': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.Orders.IPlaceOrderPart1 Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart1': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.GenericInterfaces.IBizAction`2[BizLogic.Orders.PlaceOrderInDto,BizLogic.Orders.Part1ToPart2Dto] Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart1': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.Orders.IPlaceOrderPart2 Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart2': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.GenericInterfaces.IBizAction`2[BizLogic.Orders.Part1ToPart2Dto,DataLayer.EfClasses.Order] Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart2': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: ServiceLayer.AdminServices.IAddReviewService Lifetime: Transient ImplementationType: ServiceLayer.AdminServices.Concrete.AddReviewService': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'ServiceLayer.AdminServices.Concrete.AddReviewService'.) (Error while validating the service descriptor 'ServiceType: ServiceLayer.AdminServices.IChangePriceOfferService Lifetime: Transient ImplementationType: ServiceLayer.AdminServices.Concrete.ChangePriceOfferService': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'ServiceLayer.AdminServices.Concrete.ChangePriceOfferService'.) (Error while validating the service descriptor 'ServiceType: ServiceLayer.AdminServices.IChangePubDateService Lifetime: Transient ImplementationType: ServiceLayer.AdminServices.Concrete.ChangePubDateService': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'ServiceLayer.AdminServices.Concrete.ChangePubDateService'.)
Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngine engine, ServiceProviderOptions options)

InvalidOperationException: Error while validating the service descriptor 'ServiceType: BizDbAccess.Orders.IPlaceOrderDbAccess Lifetime: Transient ImplementationType: BizDbAccess.Orders.PlaceOrderDbAccess': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)

InvalidOperationException: Error while validating the service descriptor 'ServiceType: BizLogic.GenericInterfaces.IBizAction`2[BizLogic.Orders.PlaceOrderInDto,DataLayer.EfClasses.Order] Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderAction': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)

InvalidOperationException: Error while validating the service descriptor 'ServiceType: BizLogic.Orders.IPlaceOrderPart1 Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart1': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)

InvalidOperationException: Error while validating the service descriptor 'ServiceType: BizLogic.GenericInterfaces.IBizAction`2[BizLogic.Orders.PlaceOrderInDto,BizLogic.Orders.Part1ToPart2Dto] Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart1': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)

InvalidOperationException: Error while validating the service descriptor 'ServiceType: BizLogic.Orders.IPlaceOrderPart2 Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart2': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)

InvalidOperationException: Error while validating the service descriptor 'ServiceType: BizLogic.GenericInterfaces.IBizAction`2[BizLogic.Orders.Part1ToPart2Dto,DataLayer.EfClasses.Order] Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart2': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)

InvalidOperationException: Error while validating the service descriptor 'ServiceType: ServiceLayer.AdminServices.IAddReviewService Lifetime: Transient ImplementationType: ServiceLayer.AdminServices.Concrete.AddReviewService': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'ServiceLayer.AdminServices.Concrete.AddReviewService'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)

InvalidOperationException: Error while validating the service descriptor 'ServiceType: ServiceLayer.AdminServices.IChangePriceOfferService Lifetime: Transient ImplementationType: ServiceLayer.AdminServices.Concrete.ChangePriceOfferService': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'ServiceLayer.AdminServices.Concrete.ChangePriceOfferService'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)

InvalidOperationException: Error while validating the service descriptor 'ServiceType: ServiceLayer.AdminServices.IChangePubDateService Lifetime: Transient ImplementationType: ServiceLayer.AdminServices.Concrete.ChangePubDateService': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'ServiceLayer.AdminServices.Concrete.ChangePubDateService'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)

AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: BizDbAccess.Orders.IPlaceOrderDbAccess Lifetime: Transient ImplementationType: BizDbAccess.Orders.PlaceOrderDbAccess': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.GenericInterfaces.IBizAction`2[BizLogic.Orders.PlaceOrderInDto,DataLayer.EfClasses.Order] Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderAction': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.Orders.IPlaceOrderPart1 Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart1': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.GenericInterfaces.IBizAction`2[BizLogic.Orders.PlaceOrderInDto,BizLogic.Orders.Part1ToPart2Dto] Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart1': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.Orders.IPlaceOrderPart2 Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart2': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: BizLogic.GenericInterfaces.IBizAction`2[BizLogic.Orders.Part1ToPart2Dto,DataLayer.EfClasses.Order] Lifetime: Transient ImplementationType: BizLogic.Orders.Concrete.PlaceOrderPart2': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'BizDbAccess.Orders.PlaceOrderDbAccess'.) (Error while validating the service descriptor 'ServiceType: ServiceLayer.AdminServices.IAddReviewService Lifetime: Transient ImplementationType: ServiceLayer.AdminServices.Concrete.AddReviewService': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'ServiceLayer.AdminServices.Concrete.AddReviewService'.) (Error while validating the service descriptor 'ServiceType: ServiceLayer.AdminServices.IChangePriceOfferService Lifetime: Transient ImplementationType: ServiceLayer.AdminServices.Concrete.ChangePriceOfferService': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'ServiceLayer.AdminServices.Concrete.ChangePriceOfferService'.) (Error while validating the service descriptor 'ServiceType: ServiceLayer.AdminServices.IChangePubDateService Lifetime: Transient ImplementationType: ServiceLayer.AdminServices.Concrete.ChangePubDateService': Unable to resolve service for type 'DataLayer.EfCode.EfCoreContext' while attempting to activate 'ServiceLayer.AdminServices.Concrete.ChangePubDateService'.)
Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable<ServiceDescriptor> serviceDescriptors, IServiceProviderEngine engine, ServiceProviderOptions options)
Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter<TContainerBuilder>.CreateServiceProvider(object containerBuilder)
Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
Microsoft.Extensions.Hosting.HostBuilder.Build()
BookApp.Program.Main(string[] args) in Program.cs
+
            var host = CreateHostBuilder(args).Build();
BookApp.Program.<Main>(string[] args)

Would it be possible to get the code in shape so that we can run the application?

Understanding the book and the code...

Hello, I was trying to contact the author or any who can help... is there any forum for questions about the book? I'm now at the section 2, and what I have is a full functional project, with all classes, several projects, services, repositories, etc etc... and the book only explains some parts of it... is there any part on the book that I actually create classes of the objects (book, author, etc)... how will I practice what is being shown? thank you for your help, maybe I'm missing something...

Test "TestThenIncludeSortSingle" is faling

I just cloned the repo and the first thing I did was executing all test. There is a single test failing called "TestThenIncludeSortSingle".

Here's the exception it is throwing:

Message: 
    System.InvalidOperationException : The expression 'bookAuthor.AsQueryable().OrderBy(y => y.Author.Name)' is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'. To target navigations declared on derived types, use casting ('t => ((Derived)t).MyProperty') or the 'as' operator ('t => (t as Derived).MyProperty'). Collection navigation access can be filtered by composing Where, OrderBy(Descending), ThenBy(Descending), Skip or Take operations. For more information on including related data, see http://go.microsoft.com/fwlink/?LinkID=746393.
  Stack Trace: 
    NavigationExpandingExpressionVisitor.<ProcessInclude>g__ExtractIncludeFilter|31_0(Expression currentExpression, Expression includeExpression)
    NavigationExpandingExpressionVisitor.<ProcessInclude>g__ExtractIncludeFilter|31_0(Expression currentExpression, Expression includeExpression)
    NavigationExpandingExpressionVisitor.<ProcessInclude>g__ExtractIncludeFilter|31_0(Expression currentExpression, Expression includeExpression)
    NavigationExpandingExpressionVisitor.ProcessInclude(NavigationExpansionExpression source, Expression expression, Boolean thenInclude)
    NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
    MethodCallExpression.Accept(ExpressionVisitor visitor)
    ExpressionVisitor.Visit(Expression node)
    NavigationExpandingExpressionVisitor.Expand(Expression query)
    QueryTranslationPreprocessor.Process(Expression query)
    RelationalQueryTranslationPreprocessor.Process(Expression query)
    QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
    Database.CompileQuery[TResult](Expression query, Boolean async)
    QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
    <>c__DisplayClass9_0`1.<Execute>b__0()
    CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
    QueryCompiler.Execute[TResult](Expression query)
    EntityQueryProvider.Execute[TResult](Expression expression)
    EntityQueryable`1.GetEnumerator()
    IncludableQueryable`2.GetEnumerator()
    List`1.ctor(IEnumerable`1 collection)
    Enumerable.ToList[TSource](IEnumerable`1 source)
    Ch02_IncludeSortFilter.TestThenIncludeSortSingle() line 207

And here's the original code of this test:

    [Fact]
    public void TestThenIncludeSortSingle()
    {
        //SETUP
        var options = SqliteInMemory.CreateOptions<EfCoreContext>();
        using var context = new EfCoreContext(options);
        context.Database.EnsureCreated();
        var newBook = new Book
        {
            AuthorsLink = new List<BookAuthor>
            {
                new BookAuthor {Author = new Author {Name = "Author2"}, Order = 2},
                new BookAuthor {Author = new Author {Name = "Author1"}, Order = 1},
            }
        };
        context.Add(newBook);
        context.SaveChanges();

        //ATTEMPT
        var query = context.Books
            .Include(book => book.AuthorsLink)//.OrderBy(y => y.Order))
            .ThenInclude(bookAuthor => bookAuthor.OrderBy(y => y.Author.Name));
        var books = query.ToList();

        //VERIFY
        _output.WriteLine(query.ToQueryString());
        books.Single().AuthorsLink.Select(x => x.Author.Name).ShouldEqual(new[] { "Author1", "Author2" });
    }

It would seem like it is impossible for EF to do an OrderBy() inside the ThenInclude(x => [...]) lambda. How can we make this test repass correctly?

Changing provider

I would like to change the provider to one for MariaDB. How is this done?

On fail-safe navigational collections and adding new elements

On fail-safe navigational collections and adding new elements

Context

In section 6.1.5. you show an interesting bug where a Book instance is fetched from the database without including its collection of Review instances and where that collection is initialised outside of EF Core's control, causing a merge conflict when saving the changes.

Your proposed solution is to make the setter private and to keep the collection uninitialised everywhere, so that the code will throw an exception when the property is not included with EF. This will catch any unintentional merges.

Caveat when adding new elements

But with this design in mind, how would you handle a business model that has a method to specifically populate its collection? For example, if I have the following ShoppingCart class which exposes an AddToCart(GroceryItem item) method...

public class ShoppingCart
{
  private List<GroceryItem> _items = null!;

  public Guid Id { get; private set; }
  public IEnumerable<GroceryItem> Items
  {
    get => _items;
    private set => _items = value.ToList();
  }

  public void AddToCart(GroceryItem item)
    => _items.Add(item);
}

Adding items to a fetched ShoppingCart

If I query the database and fetch an existing ShoppingCart, including its Items, then EF Core will initialise and populate the _items backing field and ensure that Items is not null. This means that any grocery items associated with that shopping cart will be loaded and that adding new grocery items before saving will work as intended.

If I query the database without including the Items property, then the AddToCart method will throw an exception, which is also acceptable. However...

Adding items to a newly created ShoppingCart

If I at some point create a new ShoppingCart and try to add items to it using the AddToCart method, then it will also throw an exception, since the _items backing field was never populated. I could change the AddToCart method in two ways; either I change the addition line to _items?.Add(item) and have it fail quietly, or I can initialise the _items backing field manually to make sure that the user can add items to a newly created cart, which seems more desirable. However...

Adding items to a fetched ShoppingCart (reprise)

If I now query the database and fetch a ShoppingCart without including the Items property, then the AddToCart method will still initialise the collection if I try to add an item to it, effectively enabling the bug you mentioned in the book.

Final thoughts

As long as a newly created ShoppingCart is saved to the database upon construction and loaded with its (empty but not null) items collection before manipulating it, then none of this would matter. But if that cart needs to be emptied or discarded, I would have to keep track of it and remove it using EF Core. This seems rather unwieldy.

Can these requirements coexist? Is there a better approach to accomplish this interaction?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.