EF Code-First from existing db add models into existing DbContext - c#

So maybe this is a stupid question, because I know that when creating a Code-first model from an existing database, Visual Studio will create a new ADO.NET Entity Data Model, and add the models in a new DbContext.
I am using Microsoft Identity in my project, hence there is already a ApplicationDbContext (IdentityDbContext). I think just having all my models in a single DbContext would be easier to handle. I am generating my code-first models from an existing database.
But Is there a way such that the generated models add up into the already existing DbContext (In this case, the IdentityDbContext?)
I have like, many models, so currently I am compelled to add each of them into existing ApplicationDbContext manually, and remove from the created DbContext.

As far as I remember there is no way to add the generated models objects to the existing DbContext automatically. You need to add them manually.
public partial class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("name=DefaultConnection")
{
}
//Add your Model objects here, You can copy them from automatically generated DbContext
public virtual DbSet<ModelObjectName> PropertyName { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Copy the modelBuilder configuration here from automatically generated DbContext here
base.OnModelCreating(modelBuilder);
}
}

Here's an alternative that works:
Mark your ApplicationDbContext class as partial:
public partial class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("DefaultConnection")
{
//unchanged
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//unchanged
}
}
Do the same with your custom Data model class, and remove the inheritance from DbContext. Also, remove constructor form it and change the OnModelCreating into a regular private method with some different name. Keep the rest unchanged.
public partial class MyDataModels
{
//unchanged
private void OnModelCreating2(DbModelBuilder modelBuilder)
{
//unchanged
}
}
Refactor (Ctrl + R + R : default shortcut) name of your Data model class, and change it to ApplicationDbContext. Visual Studio might give you a conflict warning during refactoring, ignore that and refactor. Finally, call OnModelCreating2() from OnModelCreating() method of ApplicationDbContext class.
public partial class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("DefaultConnection")
{
//unchanged
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//unchanged
OnModelCreating2(modelBuilder);
}
}
Another nice approach suggested by #DevilSuichiro is to simply inherit your Data model class from ApplicationDbContext.
Cheers!

Related

How to make edmx DbContext inherit from IdentityDbContext

Im trying to integrate asp.net identity to my existing project
i'm working with Database first, and using edmx to generate the models and context class,
Now in the Context class that is generated with edmx, i need to change the inheritance from DbContext TO IdentityDbContext but when i refresh the edmx all changes gets removed from the Context class,
So my question is how can i inherit from IdentityDbContext when using edmx
Change these
public ConfigurationContext(DbContextOptions<ConfigurationContext> options):base(options)
public IdentityDbContext (DbContextOptions<IdentityDbContext> options):base(options)
to this
public ConfigurationContext(DbContextOptions options):base(options)
public IdentityDbContext (DbContextOptions options):base(options)
Example
public class QueryContext : DbContext
{
public QueryContext(DbContextOptions options): base(options)
{
}
}

How to properly use IPluralizer in IDesignTimeServices

In my app I use code-first approach and I'm adding entities to DbContext only via IEntityTypeConfiguration<>.
My goal is to achieve pluralized table names i.e. Models for Model.
After reading documentation, article, This question
my understading would be that my pluralizer should be registered and as IPluralizer used during creating migration, however it is not.
Of course I could have implicitly use DbSet<Model> Models {get;set;} or use builder.ToTable("Models");, but in my generic scenario I'd like to avoid that, especially as I would like some models not to override abstract generic scenario.
Question is, am I doing something wrong, or I misunderstand the way it should behave
AppDesignService.cs
public class AppDesignService : IDesignTimeServices
{
public void ConfigureDesignTimeServices(IServiceCollection services)
{
Debugger.Launch();
services.AddSingleton<IPluralizer, InflectorPluralizer>();
}
}
MyDbContext.cs
public class AppDbContext : IdentityDbContext<AppUser,AppRole,Guid>
{
public EmsDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfigurationsFromAssembly(Assembly.GetAssembly(typeof(AppDbContext)));
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<DbContext, AppDbContext>(opt =>
{
opt.UseSqlServer(connectionString, sqlOpt =>
{
sqlOpt.EnableRetryOnFailure(3);
});
});
// code skipped for brevity
}
Config
public interface IEntity
{
int Id {get;set;}
}
public class Model : IEntity
{
public int Id {get;set;}
public string Name {get;set;}
}
public abstract class DbEntityConfig<T> : IEntityTypeConfiguration<T>
where T : class, IEntity
{
public void Configure(EntityTypeBuilder<T> builder)
{
builder.HasKey(m => m.Id);
}
}
public class ModelEntityConfig : DbEntityConfig<Model>
{
public void Configure(EntityTypeBuilder<Model> builder)
{
base.Configure(builder);
// Of course I want to avoid this call, cos TheOtherModel might not override base method
// builder.ToTable("Models");
builder.Property(m => m.Name).HasMaxLength(25);
}
}
Result
public partial class Test : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Model",
columns: table => new
// code skipped for brevity
}
}
Expected result:
public partial class Test : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Models",
columns: table => new
// code skipped for brevity
}
}
The linked article is incorrect. As you can see from Pluralization hook for DbContext Scaffolding EF Core documentation:
EF Core 2.0 introduces a new IPluralizer service that is used to singularize entity type names and pluralize DbSet names.
Shortly, it is used only by scaffolding commands, hence cannot be used for changing the table name model conventions.
In general migration tools use the model the way it is configured by conventions, data annotations and fluent API. So applying custom convention should be with model API inside OnModelCreating. Something like this:
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
entityType.Relational().TableName = GetTableName(entityType);
where GetTableName method implements your naming convention:
string GetTableName(IEntityType entityType)
{
// use entiityType.Name and other info
return ...;
}
Update (EF Core 3.0+): Use entityType.SetTableName(...) in place of entityType.Relational().TableName = ...

Entity Framework Database Initialization Seed is not working

I'm using EF Code-First with Identity and I have customized ApplicationUser so changed my DbContext and Initializer a little bit.
Having following classes:
public class MyDbContext : IdentityDbContext
{
public MyDbContext() : base("DefaultConnection")
{
Database.SetInitializer(new MyDbInitializer());
Database.Initialize(false);
}
}
public class MyDbInitializer : CreateDatabaseIfNotExists<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
// data initialization code here
}
}
In my unit test I create MyDbContext so I expect the Seed method gets called. Note that I don't have migration and this issue is happening in the first run.
The Seed method was being called before I inherit MyDbContext IdentityDbContext instead of DbContext. After inheriting from IdentityDbContext the Seed method is firing anymore.
ApplicationDbContext and IdentityDbContext are coming from Identity framework
Thanks for help.

entity framework 6.1 Seed & OnModelCreating not working together

I'm using EF in a Web API project with code first mode.
So far, so good, but I have Time field in a table, where I want Precision 0.
So I added the required codes in the OnModelCreating method of the DBContext class.
after that the Seed method in Configuration class was not executed.
when I comment the code in OnModelCreating, the Seed method is executing.
I would be happy if somebody could give me a reason for this, and how shall I restructure my classes to run both of the methods.
Normally I use the standard way. I have the simplest DbContext:
public partial class HarmoniaContext : DbContext {
public HarmoniaContext()
: base("Harmonia") {
}
...virtual properties or the DbSet<>...
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Nyitvatartas>()
.Property(e => e.KezdIdo)
.HasPrecision(0);
modelBuilder.Entity<Nyitvatartas>()
.Property(e => e.BefIdo)
.HasPrecision(0);
}
}
and the configuration file
internal sealed class Configuration :DbMigrationsConfiguration<HarmoniaContext> {
public Configuration() {
AutomaticMigrationsEnabled = true;
}
protected override void Seed(HarmoniaContext context) {
context.Beallitas.AddOrUpdate(b => b.Nev, ...}
context.Szerepkor.AddOrUpdate(sz=> sz.RendszerNev, ...}
}
}

DBContext overwrites previous migration

I currently have two DbContexts, ApplicationDbContext and CompanyDBContext. However the problem is that when I run my MVC web application only the CompanyDBContext gets reflected on the database and I see none of the implementation made in ApplicationDbContext being shown in the database. Both my contexts use the same connection string. The ApplicationDbContext was auto-generated when I created my MVC application as I had selected Individual accounts
Currently the ApplicationDbContext looks like this
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DevConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<CompanyDetails>();
}
}
and here is my CompanyDbContext
public class CompanyDBContext : DbContext
{
public CompanyDBContext() : base("DevConnection")
{
}
public DbSet<CompanyDetails> companies { get; set; }
}
I would delete the migrations you have now if you dont need them then use the command below to enable them separately by specifying their names and directories, so they are created separately.
enable-migrations -ContextTypeName MyCoolContext -MigrationsDirectory MyCoolMigrations
http://www.mortenanderson.net/code-first-migrations-for-entity-framework
I was curious, so I looked around, and it seems like the solution for migrations and multiple DbContexts is to have a single DbContext that serves as a complete representation of the database through which initialization and migration is handled, and disable database initialization in the constructor of all other DbContext classes.
You could do this through a combination of Database.SetInitializer and an explicit call to DbContext.Database.Initialize()
Sources
Entity Framework: One Database, Multiple DbContexts. Is this a bad idea?
Shrink EF Models with DDD Bounded Contexts
It's seems like only one dbContext can be updated at a moment. You must Enable-Migration , Add-Migration and Update-Database for each dbContext. This is the way i do it. But my dbContext were in different projects, so may be it can be the same for you! Update separately didn't overwrite my database. It works for me !
In think the problem you have, it that your database tables / migrations are not separated.
In EF6 if you work with more than one context, I recommend to specify the name for the default schema in the OnModelCreating method of you DbContext derived class (where the Fluent-API configuration is).
public partial class ApplicationDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("Application");
// Fluent API configuration
}
}
public partial class CompanyDBContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("Company");
// Fluent API configuration
}
}
This example will use "Application" and "Company" as prefixes for your database tables (instead of "dbo") in your (single) database.
More importantly it will also prefix the __MigrationHistory table(s), e.g. Application.__MigrationHistory and Company.__MigrationHistory.
So you can have more than one __MigrationHistory table in a single database, one for each context.
So the changes you make for one context will not mess with the other.
When adding the migration, specify the fully qualified name of your configuration class (derived from DbMigrationsConfiguration) as parameter in the add-migration command:
add-migration NAME_OF_MIGRATION -ConfigurationTypeName FULLY_QUALIFIED_NAME_OF_CONFIGURATION_CLASS
e.g.
add-migration NAME_OF_MIGRATION -ConfigurationTypeName ApplicationConfiguration
if ApplicationConfiguration is the name of your configuration class.
In such a scenario you might also want to work with different "Migration" folders in you project. You can set up your DbMigrationsConfiguration derived class accordingly using the MigrationsDirectory property:
internal sealed class ApplicationConfiguration: DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
MigrationsDirectory = #"Migrations\Application";
}
}
internal sealed class CompanyConfiguration : DbMigrationsConfiguration<CompanyDBContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
MigrationsDirectory = #"Migrations\Company";
}
}

Categories

Resources