Reputation: 51
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": "[email protected]"
},
"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 ?
Upvotes: 1
Views: 1494
Reputation: 51
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.
Upvotes: 0
Reputation: 65988
These are the steps you should follow when you're working with the ASP.net Core and EF 6.This is a just an example.You have to change it according to your use case.
Step 1 : project.json
Specify a single target for the full .NET Framework:
"frameworks": {
"net46": {}
}
Step 2 : Setup connection strings and dependency injection
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped((_) => new ApplicationDbContext(Configuration["Data:DefaultConnection:ConnectionString"]));
// Configure remaining services
}
Step 3 : Migrate configuration from config to code
Entity Framework 6 allows configuration to be specified in xml (in web.config or app.config) or through code. As of ASP.NET Core, all configuration is code-based.
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
Then :
[DbConfigurationType(typeof(CodeConfig))] // point to the class that inherit from DbConfiguration
public class ApplicationDbContext : DbContext
{
[...]
}
public class CodeConfig : DbConfiguration
{
public CodeConfig()
{
SetProviderServices("System.Data.SqlClient",
System.Data.Entity.SqlServer.SqlProviderServices.Instance);
}
}
Reference : ASP.NET Core and Entity Framework 6
Upvotes: 2