entity-frameworkasp.net-coreasp.net-core-mvcef-model-first

Model first DbContext creation in Entity Framework 6


In my web project I am trying to use Entity Framework 6 model first approach. Model is generated from existing database in separate project. For model generation connection string is saved in app.config of data access project. In main web project (ASP.NET Core MVC) I am trying to inject context creation in Startup.cs class.

Below is a code for context partial class. Partial class is used because context is auto generated from template.

[DbConfigurationType(typeof(EntityFrameworkConfig))]
public partial class MyEntities
{
    public MyEntities(String name) : base(name)
    {    
    }
}

For using entity framework configuration from code instead app.config that cannot be used with asp.net core projects I have config class inherited from System.Data.Entity.DbConfiguration

public class EntityFrameworkConfig : DbConfiguration
{
    public EntityFrameworkConfig()
    {
         this.SetDefaultConnectionFactory(new SqlConnectionFactory());
         this.SetProviderServices(SqlProviderServices.ProviderInvariantName,       SqlProviderServices.Instance);
    }
}

In config.json in web project i have connection string:

{
    "MailSettings": {
    "ToAddress": "foo@bar.com"
    },
    "Connection": {
    "ConnectionString": "data source=SERVER;initial catalog=DB;user id=user;password=pwd;MultipleActiveResultSets=True;App=EntityFramework;"
    }
}

In Startup.cs :

public void ConfigureServices(IServiceCollection services)
{
    ...

    String connStr = _config["Connection:ConnectionString"];
    services.AddScoped((_) => new MyEntities(connStr));
    ...

}

I am experiencing UnintentionalCodeFirstException thrown from OnModelCreating event of auto generated context class:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    throw new UnintentionalCodeFirstException();
}

Is this proper way to use Entity framework 6 model first approach with asp.net Core MVC project and what is the reason for this exception ?


Solution

  • After digging I found that solution is to provide connection string in entity framework format that enables DbContext class to load model metadata.
    In Startup.cs:

    String connStr = _config["Connection:ConnectionString"];
    String efConnString = BuildConnectionString(connStr);
    services.AddScoped((_) => new MyEntities(efConnString));  
    ....  
    ....
    private String BuildConnectionString(String cs)
    {
        EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
        entityBuilder.Provider = "System.Data.SqlClient";
        entityBuilder.ProviderConnectionString = cs;
        entityBuilder.Metadata = @"res://*/XXXWebModel.csdl|
                            res://*/XXXWebModel.ssdl|
                            res://*/XXXWebModel.msl";
        return entityBuilder.ToString();
    }
    

    When connection string is provided in format that doesn't contain metadata information where to look for generated model entity framework finds that code first approach is used and that is why method OnModelCreating is called that throws exception :

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }  
    

    Sending connection string formated as entity framework connection string that contains metadata information solves problem.