RavenDb Config and DocumentStore abstraction? - ravendb

I am using RavenDb across multiple projects and solutions to access three different databases that are all part of the same product. For instance, I have multiple MVC projects that fetch user info and some data out of the 'web' centric database and the 'backend' database, using '-' for the id override (but I need this only for a subset of classes in the 'web' db). And then I have another 'backend' database that is used by services (as well as the MVC projects). And finally a third temp/scratch database I use by another set of services to build the backend db. And of course, all of these are being accessed from different class libraries and even console test, seed, and integration test apps.
Managing all of these is becoming quite a nuisance. Every time I create a new console app or class library that access the db, I have to setup config and raven packages for each project, make sure indexes are built, etc.... Not to mention running update on all nuget updates, or in my case, installing a new unstable version of the server/client binaries.
Is there an easier way to manage this?
I tried to abstract the DocumentStore creation and initialization, as well as index creation into it own project and reference that. But the other projects then had to manually add newtonsoft.json (and nlog) from the package directory.
As well, I am getting the following when I try and abstract the DocumentStore into a class with a static property:
StackTrace of un-disposed document store recorded. Please make sure to dispose any document store in the tests in order to avoid race conditions in tests.
Anyone have any thoughts on handling these issues?
Thanks

I don't think that the manual addition of the references is a big issue, but you can add the actual nuget references as well.
Note that the DocumentStore not disposed error is something that only happened in the unstable (debug builds), and won't happen on release builds.

Related

Is it okay to initialize/seed a database data during Startup of an application?

We would like to programmatically ensure that a database table has a certain set of rows (based on a sometimes-changing enum). We are using EF Core 2.2 with code-first migrations and are looking for the right place to seed this data. We had thought that adding a seeding method to our Startup.cs would be a good idea, but Microsoft's documentation says
The seeding code should not be part of the normal app execution as this can cause concurrency issues when multiple instances are running and would also require the app having permission to modify the database schema.
Is the code in Startup.cs considered "part of the normal app execution"?
Our app currently only runs with 1 instance, but there might be multiple in the future. Plus, we have an Azure Functions app and a console app which might also need to ensure that the database table has the correct rows before executing. Despite these concerns, I have seen accepted and upvoted answers on other threads saying that initializing as part of Startup.cs is okay. Will we be shooting ourselves in the foot by doing this?
From the docs:
Depending on the constraints of your deployment the initialization code can be executed in different ways:
Running the initialization app locally.
Deploying the initialization app with the main app, invoking the initialization routine and disabling or removing the initialization app.
My interpretation from this is that you could deploy a console app using publishing profiles that ensured the database seed at launch.

Could not load type 'System.Data.Entity.Core.Mapping.EntityContainerMapping'

When I debug the following code, I receive the message "System.TypeLoadException was caught" when I perform the Delete().
Using db As New ScholarshipEntities
db.ApplicationHistories.Where(Function(h) h.HistoryTypeId = 0).Delete()
db.SaveChanges()
End Using
I am using EF 6.1 in Visual Studio 2013. I also have the EntityFramework.Extended library installed.
I have no trouble querying results. I thought the bug might occur when the Where method has no results, but that is not the case. I also have no problem adding new models (.edmx), which was a problem some people with this exception had.
I just recently upgraded to EF 6.1 and installed the Extended library. This is my first time using one of the extended methods. I've un-installed and re-installed the nuget packages with no success.
IntelliTrace shows the following exceptions from the Delete() call (in order):
'EntityFramework.Reflection.DynamicProxy' does not contain a definition for 'InternalQuery'
Cannot implicitly convert type 'EntityFramework.Reflection.DynamicProxy' to 'System.Data.Entity.Core.Objects.ObjectQuery<Scholarship.ApplicationHistory>'
Could not load type 'System.Data.Entity.Core.Mapping.EntityContainerMapping'
I've added an issue on the Extended library's github.
Update
I've reinstalled EF and the EF.Extended library with no luck. I am able to use RemoveRange in its place. I am able to create a new project, install the packages, add a model mapped to the same database, and successfully use Delete. Obviously, the problem is in my current solution.
In my solution, I have an ASP.NET project and a regular library project. In the ASP project, a page's code behind calls a method in the library RemoveHistory. The library contains classes for the business logic and data access. Both classes implement interfaces. The actual Delete occurs in the data access class. My model also resides in this library project.
I may be able to create a completely new project and bring everything over, but that will take quite some time. Even if I did, I want to understand why it doesn't work in the first place, so that I don't have to repeat this process.
If you want to delete certain rows do it like that:
Using db As New ScholarshipEntities
db.ApplicationHistories.RemoveRange(db.ApplicationHistories.Where(Function(h) h.HistoryTypeId = 0))
db.SaveChanges()
End Using
If you want to remove single entity do it like that:
Using db As New ScholarshipEntities
db.ApplicationHistories.Remove(db.ApplicationHistories.Single(Function(h) h.HistoryTypeId = 0))
db.SaveChanges()
End Using
I "solved" the issue some time ago. I'll eventually go back to try and reproduce the problem to confirm my suspicions.
There were multiple versions of Entity Framework installed in the solution. This didn't appear to affect basic EF functionality, though I'm sure it did in some subtle, potentially buggy fashion.
Every time the solution was opened, NuGet would state that it couldn't complete uninstallation. Uninstalling and restoring via NuGet was unsuccessful, and the packages had to be deleted manually. Once completely removed, I installed the packages again. This resolved the issue.
I wish I could give a more technical answer, though the basic reason was forgetting to look closer at the packages folder and configuration.

Entity Framework 5 entity in separate dll

I have a DLL that is a logging component that we use in many different projects. This logging component is designed to be entirely self-contained, and thus it must have its database connection string internal to it. In this project, it is completely unacceptable to require that its connection string be copied to the app.config of any project that uses it.
This has been working great for years, but now we have found that mixing its older ADO tech with new apps that use EF results in horrible performance when the logging is being done. For example, adding a single log entry when the application starts results in a > 30 second delay before the app opens.
So to combat this, I have re-written this component to use EF.
The problem is under the current EF (version 4.4 since we are targeting .Net Framework 4.0) does not offer a constructor to DBContext that allows you to specify the entire connection string. The code attempts to change the Database.Connection.ConnectionString, but the DBContext object insists on looking in the App.Config for the connection string even though we are giving it a new one.
I must get around this behavior.

Accessing a single RavenDB from different applications

I have a web project that stores objects in raven db. For simplicity the classes live in the web project.
I now have a batch job that is a separate application that will need to query the same database and extract information from it.
Is there a way I can tell raven to map the documents to the classes in the batch job project that have the same properties as those in the web project.
I could create a shared dll with just these classes in if that's needed. seems unnecessary hassle though
As long as the structure of the classes you are deserializing into partially matches the structure of the data, it shouldn't make a difference.
The RavenDB server doesn't care at all what classes you use in the client. You certainly could share a dll, or even share a portable dll if you are targeting a different platform. But you are correct that it is not necessary.
However, you should be aware of the Raven-Clr-Type metadata value. The RavenDB client sets this when storing the original document. It is consumed back by the client to assist with deserialization, but it is not fully enforced. The logic basically is this:
is there ClrType metadata?
if yes, do we have that type loaded in the current app domain?
if yes, then deserialize into that type
if none of the above, then deserialize dynamically and cast into the type
requested (basically, duck-typing)
You can review this bit of the internals in the source code on github here.

Migration patch from NServiceBus 2.6 to NServiceBus 3.0

I have an existing NServiceBus 2.6 application that I want to start moving to 3.0. I'm looking for the minimum change upgrade in the first instance. Is this as simple as replace the 2.6 DLLs with the 3.0 Nuget packages or are there other considerations?
For the most part the application migration is quite straight forward, but depending on your configuration and environment, you may need to make the following changes:
The new convention over configuration for endpoints may mean you will need to rename your endpoints to match your queue names (#andreasohlund has a good post about this).
persistence of saga, timeouts, subscriptions etc. now defaults to RavenDb, so if you use SQL Server to persist data, you need to make sure you have to correct profile and endpoint configuration. For SQL Server storage, make sure you add a reference to NServiceBus.NHibernate as it is no longer part of the core.
Error queues are now referenced differently using different configuration ie. use MessageForwardingInCaseOfFaultConfig instead of the regular MsmqTransportConfig error property. You should still be able to use it, but it will look for the MessageForwardingInCaseOfFaultConfig first.
Other than that, I don't think you need to do anything else to get you upgrade working. I modified some of my message definitions to take advantage of the new ICommand and IEvent interfaces as a way communicatinf intent more clearly.
Anyway, I'm sure there will be some cases that are specific to your environment that will require different changes but I hope this helps a bit.