Entity Framework and Jenkins working together

Posted by:

While working on <PROJECT_NAME_HERE>, I began to run into an issue on the UAT server. Several test cases were failing while running under Jenkins, all with the same cryptic error message. You may have seen this error in your own tests as well. It states:
System.InvalidOperationException:

The Entity Framework provider type ‘System.Data.Entity.SqlServer.SqlProviderServices,EntityFramework.SqlServer, Version=6.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089’ for the ‘System.Data.SqlClient’ ADO.NET provider could not be loaded.

Make sure the provider assembly is available to the running application.

This is rather confusing because the app was clearly using SQL Server and making database connections correctly, indicating that it should work correctly. Yet these tests failed consistently, 100% of the time. I started my investigation into debugging it.

  1. Check the unit test project as well as the rest of the projects to ensure that the assembly is actually present. Yes, it’s there, so that’s not it.
  2. Check that the ‘Copy Local’ attribute for this reference is set to true. Yes, annoyingly, it was set to true and the file was in fact on UAT.
  1. Check the unit test app configuration file to ensure that the SQL provider is specified…Argh, yes, it’s there!
  1. Ensure all tests locally are identical to what’s on UAT…YES %@#*&#*&#$!
    (In my frustration I neglected to take a file compare screenshot, but everything on UAT was identical to SVN which was identical to my local build.)

 

At this point I figured someone else must have had this problem and did some digging around online, which brought me to this block of code:

var type = typeof(System.Data.Entity.SqlServer.SqlProviderServices);
if (type == null)
     throw new Exception("Do not remove, ensures static reference to System.Data.Entity.SqlServer");

Including that block into the test case instantiation module fixes the problem completely. This appears to be a known issue for Entity Framework 6+; unless you have a code-level reference to the SQL provider service, the Entity Framework assembly won’t be copied to the output folder where the unit tests are actually run. The compiler is overzealous in trying to remove assemblies that it doesn’t need, and accidentally tosses out the SQL Server assembly; that is, if you don’t add a block of code deliberately instantiating it to ensure it’s there.
We don’t do anything with that type variable except to null check it and move on. It isn’t used anywhere else, but without it, the tests keep failing. So our final code looks like this:

public static void InitializeTestRun(TestContext testContext) {
     InjectionModule.RegisterContextBinding<IPOREntity, PORContext>()
     InjectionModule.RegisterContextBinding<IConnectRXEntity, ConnectRXContext>();
     Resolver.SetModule(new TestModule(1));
     var type = typeof(System.Data.Entity.SqlServer.SqlProviderServices);

     if (type == null)
          throw new Exception("Do not remove, ensures static reference to System.Data.Entity.SqlServer");
}

All we’re doing here is setting up the binding for our contexts, setting the ID we want to use for the tests (in this case, 1), and then telling the compiler that we do in fact actually need SQL server.
That’s it!

Hope this helps!

 

0

Add a Comment