Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setup EF Trace on an Entities ObjectContext without passing in the connection name

I'm writing a reusable base repository class where the developer will pass in a generic representing the ObjectContext and the base repository will create an instance of it with Activator.CreateInstance. When debugging I want to make use of the nuget package CommunityEFProviderWrappers.EFTracingProvider. So my code to setup the object context looks like this:

    public void RenewDataContext()
    {
#if DEBUG
        // get the default container name
        var containerName = Activator.CreateInstance<T>().DefaultContainerName;

        // create an instance of the object context using EF Trace
        Context = (T)Activator.CreateInstance(typeof(T), EFTracingProviderUtils.CreateTracedEntityConnection(containerName));
        Context.EnableTracing();

#else
        Context = Activator.CreateInstance<T>();
#endif
    }

The problem is that this always throws the following error when it tries to create an instance of the ObjectContext with the EFTracingProvider: "Schema specified is not valid. Errors: \r\n(0,0) : error 0175: The specified store provider cannot be found in the configuration, or is not valid."

If I replace containerName with the name of the connection string in the web config and don't do the first Activator.CreateInstance<T>() then it works fine. So the issue has something to do with the fact that I create the first instance and then the second.

Here is what I have tried:

  1. dispose and null out the first instance.
  2. close the connection on the first instance.
  3. put the first instance in a using statement.
  4. explicitly define the assembly containing the ObjectContext in the connection string in the web.config in the startup project (MetadataException when using Entity Framework Entity Connection)

I am trying to avoid having the developer pass in the generic type of the ObjectContext AND the name of the connection string. That seems kind of redundant.

So my question is: How do I get the connection name from the generic representing the object context and still be able to use it to create an instance of the object context using the EntityConnection generated by EF Trace?

My question is about why this method doesn't work, not about possible work arounds.

like image 909
bygrace Avatar asked Nov 08 '12 14:11

bygrace


People also ask

Does DbContext dispose close connection?

So if you have more than one DbContext with the same connection whichever context is disposed first will close the connection (similarly if you have mixed an existing ADO.NET connection with a DbContext, DbContext will always close the connection when it is disposed).

How do I change the connection string in Entity Framework?

If you want to change the connection string go to the app. config and remove all the connection strings. Now go to the edmx, right click on the designer surface, select Update model from database, choose the connection string from the dropdown, Click next, Add or Refresh (select what you want) and finish.

How do you close a connection in Entity Framework?

If the object context opens the connection during an operation, it will always close the connection when the operation is complete. If you manually open the connection, the object context will not close it. Calling Close or Dispose will close the connection.


1 Answers

Here is your solution, add the folowing code to your config file:

<system.data>
  <DbProviderFactories>
    <add name="EF Caching Data Provider"
         invariant="EFCachingProvider"
         description="Caching Provider Wrapper"
         type="EFCachingProvider.EFCachingProviderFactory, EFCachingProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
    <add name="EF Tracing Data Provider"
         invariant="EFTracingProvider"
         description="Tracing Provider Wrapper"
         type="EFTracingProvider.EFTracingProviderFactory, EFTracingProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
    <add name="EF Generic Provider Wrapper"
         invariant="EFProviderWrapper"
         description="Generic Provider Wrapper"
         type="EFProviderWrapperToolkit.EFProviderWrapperFactory, EFProviderWrapperToolkit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
  </DbProviderFactories>
</system.data>

The problem occurs in EFTracingProviderUtils.CreateTracedEntityConnection method. It searches for .Net Framework Data Provider - EFTracingProvider, which must be specified in your config file. When it can't find it, it can't build such connection string for its purposes:

"metadata=reader://998e0526-8372-4bf9-83d3-949dececce96; provider=EFTracingProvider; provider connection string=\"wrappedProvider=;data source=.\SQLEXPRESS;attachdbfilename=|DataDirectory|\database.mdf; integrated security=True; connect timeout=30; user instance=True; multipleactiveresultsets=True; App=EntityFramework\";"

As you can see metadata reader specified it this connection string, here will be MetadataException which is thrown when EF can't find EFTracingProvider. It is just problem with third-party method.

You can call next method and receive same result without any changes to your config:

EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(containerName, new string[]{});
like image 57
Igor Lozovsky Avatar answered Oct 06 '22 18:10

Igor Lozovsky