Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF6 'ModelConfiguration' set but not discovered

I have the following libraries:
EntityMODEL.dll (contains POCO classes)
EntityDAL.dll [references EntityMODEL.dll]
EntitySERVICE.dll [references both EntityMODEL.dll and EntityDAL.dll]
EntityTEST.dll [unit tests with references to EntitySERVICE.dll and EntityMODEL.dll]

The EntitySERVICE.dll and EntityMODEL.dll are all that need to be referenced by the outside world (e.g. from EntityTEST.dll), meaning that the outside world does not need to reference EntityDAL.dll or Entity Framework.

Here is my DbContext from EntityDAL.dll ...

EntityDAL.dll | DbContext

public class FooContext : DbContext
{
    public FooContext()
    {
        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.ProxyCreationEnabled = false;
    }

    public DbSet<Bars> Bars{ get; set; }

    // NESTED DbConfiguration
    public class ModelConfiguration : DbConfiguration
    {
        public ModelConfiguration()
        {
            this.SetHistoryContext( .... )
        }
    }
}

When running unit tests from EntityTEST.dll all works fine.


I have several of these 'packages' (all following the same MODEL/DAL/SERVICE structure) in my solution each dealing with different related groups of underlying entities.

To coordinate the activity across these multiple Entity 'packages', I have an 'orchestration' (or task) layer with the following libraries:

TaskMODEL.dll [contains POCO classes]
TaskSERVICE.dll [references TaskMODEL.dll, EntitySERVICE.dll and EntityMODEL.dll]
-- also provides transformations between TaskMODEL.dll classes and EntityMODEL.dll classes
TaskTEST.dll [references TaskSERVICE.dll and TaskMODEL.dll]

Now, when running a test from TaskTEST.dll (which calls methods in TaskSERVICE.dll, which transforms and then calls EntitySERVICE.dll), I get the following error:

... threw exception:<br/>
System.InvalidOperationException: An instance of 'ModelConfiguration'
was set but this type was not discovered in the same assembly as the
'FooContext' context.  Either put the DbConfiguration type in the same
assembly as the DbContext type, use DbConfigurationTypeAttribute on the
DbContext type to specific the DbConfigurationType, or set the
DbConfiguration type in the config file.

This error occurs during instantiation of FooContext. Having put a debug breakpoint on the FooContext constructor I can see that when the constructor is entered from the first test (EntityTEST), the code immediately drops down to the constructor of ModelConfiguration and all is well. However, when the test is initiated from TaskTEST the above error is thrown instead of dropping down to the constructor of ModelConfiguration.

As you can see from the initial code snippet above ModelConfiguration class is nested under FooContext, so it is definitely in the same assembly. Additionally, the same library behaves fine when the test is initiated from EntityTEST.dll. It is only when there are more layers and the test is initiated from TaskTEST.dll that there is a problem. As the ModelConfiguration class is in the same assembly, I have not mentioned ModelConfiguration settings in the app.config in any of my projects.

Summary

1)             EntityTEST > EntitySERVICE > EntityDAL = GOOD
2) TaskTEST > TaskSERVICE > EntitySERVICE > EntityDAL = ERROR

Anybody seen this gotcha before?

UPDATE

As mentioned above, I have several EntitySERVICE/EntityMODEL/EntityDAL combinations in my solution. Having played around a bit and naming each DAL's ModelConfiguration class to include the DLL name (so they're not all called ModelConfiguration across all combinations), the error can be restated as:

... threw exception:<br/>
System.InvalidOperationException: An instance of 

    'ModelConfiguration_NOT_THE_FOO_CONFIG'

was set but this type was not discovered in the same assembly as the
'FooContext' context.  Either put the DbConfiguration type in the same
assembly as the DbContext type, use DbConfigurationTypeAttribute on the
DbContext type to specific the DbConfigurationType, or set the
DbConfiguration type in the config file.

In other words, the environment appears to have loaded the ModelConfiguration from the first DAL dll used during the test and then expects to find the same ModelConfiguration for subsequent DAL dlls that it uses.

Does this mean that we can only have ONE ModelConfiguration class across the whole solution???

like image 410
Neil W Avatar asked Nov 12 '13 12:11

Neil W


2 Answers

According to documentation on Entity Framework, configuration is defined globally on application level and then propagates to every loaded assembly: http://go.microsoft.com/fwlink/?LinkId=260883

If you have several assemblies with separate configurations defined in each of them, then only configuration from the first loaded assembly will be used globally. All other configurations will be ignored and substituted with a global reference to the first loaded configuration. It then propagates to every other loaded assembly.

If you have several DBCotntext classes in different assemblies, they must not define local configurations per assembly. Instead, calling application should define own configuration and set it for all of them as follows:

  public class MyConfiguration : DbConfiguration
  {
    public ReporsitoryConfiguration()
    {
      // your code here
    }
  }

and then:

DbConfiguration.SetConfiguration(new MyConfiguration());
like image 137
Boris Zinchenko Avatar answered Nov 20 '22 15:11

Boris Zinchenko


I am having the same issue.

Seems like the answer related to the explanation here:

http://msdn.microsoft.com/en-us/data/jj680699

There are cases where it is not possible to place your DbConfiguration class in the same assembly as your DbContext class. For example, you may have two DbContext classes each in different assemblies. There are two options for handling this.

The first option is to use the config file to specify the DbConfiguration instance to use. To do this, set the codeConfigurationType attribute of the entityFramework section. For example:

...Your EF config... The value of codeConfigurationType must be the assembly and namespace qualified name of your DbConfiguration class.

The second option is to place DbConfigurationTypeAttribute on your context class. For example:

[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext
{
}

The value passed to the attribute can either be your DbConfiguration type - as shown above - or the assembly and namespace qualified type name string. For example:

[DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssembly")]
public class MyContextContext : DbContext
{
}

I am still getting that error using the DbConfigurationTypeAttribute

like image 31
Motty Avatar answered Nov 20 '22 14:11

Motty