Code Like a Pro in C# (9781638356417) by Rodenburg Jort
Author:Rodenburg, Jort [Rodenburg, Jort]
Language: eng
Format: epub
Publisher: Simon & Schuster
Published: 2021-07-09T22:00:00+00:00
8.7.4 Querying for pending changes in Entity Framework Core
If we look back at the SaveChangesAsync method in the stub, we see that we access context.Booking before calling base.SaveChangesAsync. Accessing the Booking DbSet before saving any changes we made to the internal DbSets to the database means that there is nothing in the booking collection yet, causing a NullReferenceException, which we catch in the CreateBooking method. The CreateBooking method then throws a CouldNotAddBookingToDatabaseException.
The solution is simple: call base.SaveChangesAsync before accessing context .Booking. Because we are using an in-memory database, we can commit a Booking object to the database during the failure path unit test because the TestInitialize method creates a new instance of the database context (and implicitly wipes the database) before the next test. The important part of the test is that the exception gets thrown. That means we do not need the default case in our switch statement anymore. That being said, letâs change the executed logic on the non-default statement to return an integer of value 1. The SaveChangesAsync method returns (in a nonstubbed scenario) the number of entries written to the database. I see no reason to deviate from that pattern in the stub. We are mimicking its operations, after all.
The only purpose of the nondefault switch value (in this scenario) is to satisfy the required return type of Task<int>. By returning a value of 0, we complete the method and do no harm. We still throw an exception in case CustomerID is anything but 1, as shown in the next listing.
Listing 8.16 Stubbed SaveChangesAsync method with base SaveChangesAsync call
public override async Task<int> SaveChangesAsync(CancellationToken ⥠cancellationToken = default) { await base.SaveChangesAsync(cancellationToken); ⶠreturn base.Booking.First().CustomerId switch { ⷠ1 => 1, ⸠_ => throw new Exception("Database Error!") ⹠}; }
â¶ Calls the nonstub SaveChangesAsync
â· Switches based on the CustomerId
⸠If the CustomerID is 1, returns a 0
â¹ If the CustomerID is not 1, throws an exception
If we run the test now, we see it passes. However, we have an additional problem to consider here. Currently, weâre throwing an exception if the CustomerId is anything but 1, but our changes have already been saved to the database. We really should test the CustomerID before saving to the database. To do this, we need to be able to access the pending changes to the database. Entity Framework Core lets us do this by querying its internal StateTracker for entities with an EntityState of Added as follows:
IEnumerable<EntityEntry> pendingChanges = ⥠ChangeTracker.Entries().Where(e => e.State == EntityState.Added);
The resulting IEnumerable collection contains only our pending changes. What we really want, though, is the Entity objects on the pending changes. We can use a LINQ Select statement to grab only the Entity objects, as shown here:
IEnumerable<object> entities = pendingChanges.Select(e => e.Entity);
From here, we can cast the EntityEntry to our Booking type and grab the CustomerId. To cast (and select only) the entities mapped to a Booking, we can use the OfType<T> method on the IEnumerable as follows:
IEnumerable<Booking> bookings = ⥠pendingChanges.Select(e => e.Entity).OfType<Booking>();
We can
Download
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.
API Testing and Development with Postman by Dave Westerveld(3675)
Learning C# by Developing Games with Unity 2020 by Harrison Ferrone(2672)
Software Architecture for Busy Developers by Stéphane Eyskens(2375)
2021 Beginners Guide to Python Programming Language: A Crash Course to Mastering Python in One Hour by Elmer Gary & Elmer Gary(1885)
Machine Learning for Algorithmic Trading by Stefan Jansen(1635)
Hands-On ROS for Robotics Programming by Bernardo Ronquillo Japón(1577)
Delphi GUI Programming with FireMonkey by Andrea Magni(1461)
Game Development Projects with Unreal Engine by Hammad Fozi & Goncalo Marques & David Pereira & Devin Sherry(1405)
Cloud Native with Kubernetes by Alexander Raul(1380)
Datadog Cloud Monitoring Quick Start Guide by Thomas Kurian Theakanath(1350)
Software Architecture Patterns for Serverless Systems by John Gilbert(1343)
Practical Node-RED Programming by Taiji Hagino(1336)
Automate It with Zapier by Kelly Goss(1322)
Practical System Programming for Rust Developers by Prabhu Eshwarla(1313)
Delphi Programming Projects by William Duarte(1298)
Mastering React Test-Driven Development by Daniel Irvine(1293)
Developing Multi-Platform Apps with Visual Studio Code by Ovais Mehboob Ahmed Khan & Khusro Habib & Chris Dias(1257)
Ghidra Software Reverse Engineering for Beginners by A. P. David(1246)
Learn Spring for Android Application Development by S. M. Mohi Us Sunnat(1239)
