jonpsmith / efcoreinaction-secondedition Goto Github PK
View Code? Open in Web Editor NEWSupporting repo to go with book "Entity Framework Core in Action", second edition
Home Page: https://bit.ly/EfCoreBook2
License: MIT License
Supporting repo to go with book "Entity Framework Core in Action", second edition
Home Page: https://bit.ly/EfCoreBook2
License: MIT License
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?
Hi Jon;
I just download the three parts. But in part 3 the solution is missing a series of projects. Could you please investigate?
Thanks!
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?
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...
Hi Jon;
I'm enjoying your well written book and would like to share my opinion with others via the customer review. However, I can't find any link (even when I'm logged in) in Manning site to give review and vote. I've sent them an email but no response.
Do you know the link?
https://www.manning.com/books/entity-framework-core-in-action-second-edition?query=ef#reviews
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?
I would like to change the provider to one for MariaDB. How is this done?
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.
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);
}
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...
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...
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.
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.