Using RavenDb in a Core 3.x console application

For those using RavenDB in an ASP.Net hosting environment, everything Just Works after a migration to .NET Core 3.x, but for those of us running a generic host as a standalone application it’s a different story. While the Raven team is hard at work migrating the server to 3.1, we are still left with dependency injection interfaces from ASP.Net Core 2.1 when configuring a client. The necessary changes only touch three classes, and only a couple lines of code at that, but it still helps to have a working version at hand when spiking out a new project. You can download a single file with all the necessary classes in it, be sure to add Microsoft.Extensions.Hosting if you haven’t already, and confirm that when you call services.AddRavenDbDocStore() you have that file in the same namespace as the program/setup class so that it ‘wins’ the binding.

For anyone curious as to why this happened, read on. When Microsoft released .Net Core 3.0 they adapted the WebHost startup model into something more generic that allowed developers to reuse application startup code between a web app and a console/service application. This was a fantastic improvement for keeping code consistent and reducing duplication, but it necessitated breaking backwards compatibility (thank you Microsoft for taking that hit. Java, I have 3 words for you – Generic Type-erasure). Where previously an application or framework could work with its hosting environment by taking a dependency on IHostingEnviroment that API is now obsolete, and specific to ASP.Net hosting scenarios anyway. The replacement is in the Nuget Package Microsoft.Extensions.Hosting and named IHostEnvironment, which is actually API compatible with the legacy interface. Any library which needs access to the environment of the host in which it is executing can take a dependency on that IHostEnvironment service, and will get the correct type of host injected at runtime regardless of if it is run in ASP.Net or a console .NET application. Since Raven.Client was built against 2.x it is using that obsolete interface, which is not compatible with the 3.1 hosting bits. There may be other libraries out there with this same problem, and if you encounter any the easiest solution is to grab the source code and change references from IHostingEnvironment to IHostEnvironment.

Planning for change

Building software is fun, but building something that is easy to maintain and reason about can be a real challenge. Coming soon I will be taking a journey through an entire application, from inception and feature discovery through to deployment, with all the fun and frustration that comes with that. I wanted to title it “Change is the only constant” but it turns out there’s a really good book on calculus with that title. So for now the title is “planning for change.” Here is a preview of the ‘chapters’ I see coming out of this adventure:

  1. Inception, and figuring out what MVP is
  2. Platform choice, there’s value in using what you already know
  3. Don’t try to build a skyscraper on day one
  4. First feature
  5. Writing automated tests
  6. Deploying what we have
  7. Why early user feedback is important
  8. First refactor for maintainability
  9. Authentication doesn’t need to be so freaking painful
  10. Discovering new requirements
  11. What is this Domain Driven Development thing all about?
  12. Complexity is increasing, time to refactor again
  13. Why Dependency Injection is so powerful
  14. Bounded contexts and SOA
  15. CQRS for fun and profit
  16. Refactoring our tests to make it easier to add more
  17. Going mobile
  18. Side trip down response formatting lane
  19. SignalR makes life more interesting
  20. I don’t know how to pronounce it, but man I love Redis
  21. Distributed systems can be fun
  22. Eventual Consistency where it makes sense
  23. Moving to microservices
  24. Different databases for different problems
  25. Deployment update
  26. Cashing in on response caching
  27. Getting the most out of my favorite database