Entity Framework Core Issue - Update-Database Creating "User" Schemas - sql

I've been working for quite a while on a production application using .NET Core 2.0 (originally 1.0) & EF Core.
This is a Code-First designed application, so all database changes have been made via Migrations.
Up until a recent deployment, Update-Database would make the changes correctly - however, recently it has been creating new schemas each time a model is added (instead of adding to the dbo schema like normal).
Example:
New Class Model: Test.cs
Table created in Database: DOMAIN\CurrentUser.Test
Any ideas on why this would be happening?
I suppose I can dig deep into the migrationBuilder to figure out how it is making Schema decisions, but seems like something simple must have changed to change the behavior.
"DOMAIN\CurrentUser" has dbo rights on the server in question.

For changing schema from EF Core, try to configure with builder.HasDefaultSchema("newschema"); or builder.Entity<User>().ToTable.
For changing the schema for all tables.
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<User> User { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.HasDefaultSchema("newschema");
}
}
For chaning the schema for specific table.
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<User> User { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<User>().ToTable("User", "newSchema");
}
}

Related

.Net Core 3.1 Migrations. IdentityDbContext does not inherit DbContext

I'm using MySql and trying to add asp.net Identities to it via migrations.
I have ApplicationDbContext class:
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
Also I already have all migrations and configurations. So this project works well on another machine.
But when I'm trying to run command Enable-Migrations -ContextTypeName Web.Data.ApplicationDbContext I'm getting an error "The type 'ApplicationDbContext' does not inherit from DbContext. The DbMigrationsConfiguration.ContextType property must be set to a type that inherits from DbContext."
How could I fix it?

OnModelCreating code refactoring from EF6 to EF core 3.1

I am trying to refactor the OnModelCreating method before when it used to be a part of ASP.net: :
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Types().Configure(c => c.ToTable(c.ClrType.Name.ToUpper()));
modelBuilder.Properties().Configure(c => c.HasColumnName(c.ClrPropertyInfo.Name.ToUpper()));
....
But now after migrating to .netCore 3.1 I am getting this error
'ModelBuilder' does not contain a definition for 'Types' and no accessible extension method 'Types' accepting a first argument of type 'ModelBuilder' could be found
Could you please suggest a way to refactor the code properly while keeping the same old logic
Thanks for your help
According to your code, it seems that you want to change the Table Name and set the Column Name, if that is the case, you could try to refer the following code to override the OnModelCreating method:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//Write Fluent API configurations here
//Property Configurations
modelBuilder.Entity<Blog>().ToTable("BLOGS");
modelBuilder.Entity<Blog>()
.Property(b => b.BlogId)
.HasColumnName("BLOG_ID");
}
}
More detail information, please check the following links:
EF Core Fluent API Configuration
Entity Types # Table Name
Column names
How to Specify Entity Framework Core Table Mapping?
Edit:
And what about the second config rule ;
modelBuilder.Properties().Configure(c =>
c.HasColumnName(c.ClrPropertyInfo.Name.ToUpper())); I cant go through
every column there to just make it uppercase
There have an open source plugin (Naming Conventions) which might help you. By using its UseUpperCaseNamingConvention, it could change the table and Column name to Uppercase.
You could refer to the following steps to use it:
Add the EFCore.NamingConventions from the Nuget.
Enable the naming convention in your model's OnConfiguring method:
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
public DbSet<Customer> Customers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.EnableSensitiveDataLogging();
optionsBuilder
.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=true") //database connection string.
.UseUpperCaseNamingConvention();
}
}
After migration, you can see the Model Snapshot, it will change the Table and Column name as below:
Then, after update the database, the table like this:
[Note] The Naming Conventions is a community-maintained plugin: it isn't an official part of Entity Framework Core and isn't supported by Microsoft in any way.

How to add new colum into Identity RoleClaims table (asp net core)

I'm trying to add a column to the identity (asp net core) RoleClaims table but I find content just to extend the roles and users classes and not to RoleClaims.
Could someone help with examples or point out content.
You would need to create a new class to extend the RoleClaim. Here is an example of how to do it if your key type is string:
public class ApplicationRoleClaim : IdentityRoleClaim<string>
{
public virtual ApplicationRole Role { get; set; }
}
You can add whatever new properties you want to this class then create a migration to add them as table columns.
You would also need to tell your IdentityDbContext to use this new class as well. Here is an example from the docs:
public class ApplicationDbContext
: IdentityDbContext<
ApplicationUser, ApplicationRole, string,
ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin,
ApplicationRoleClaim, ApplicationUserToken>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
EDIT:
With your custom ApplicationRoleClaim class, you could override OnModelCreating as well. This is an example from the docs:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
⋮
modelBuilder.Entity<IdentityRoleClaim<string>>(b =>
{
b.ToTable("MyRoleClaims");
});
⋮
}
Reference: Identity model customization in ASP.NET Core
I made a demo with asp.net core 2.2 and it worked well ,try the following code , customize ApplicationRoleClaim to add other propertyies.
public class ApplicationRoleClaim: IdentityRoleClaim<string>
{
public string Description { get; set; }
}
Then use DbSet<TEntity> class which represents a collection for a given entity within the model and is the gateway to database operations against an entity to add the new column to table
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<ApplicationRoleClaim> ApplicationRoleClaim { get; set; }
}
Finally add-migration and update-database.

No parameterless constructor defined for this object in asp.netcore migrations

I am new to ASP.NET Core. learning new version of .NET Core 2.0 using VS Code. I got stuck while doing creating database using migration. First, it gives an exception of implementation of IDesignTimeDbContextFactory. After solving this, it still gives an exception of
No parameterless constructor defined for this object
Here's my code for DbContextClass:
public VegaDbContext CreateDbContext(string[] args)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var builder = new DbContextOptionsBuilder<VegaDbContext>();
var connectionString =
configuration.GetConnectionString("DefaultConnection");
builder.UseSqlServer(connectionString);
return new VegaDbContext(builder.Options);
}
I had tried a couple of ways when I was experimenting with ef core. I faced similar issues too. Finally I found services working great. First you will need to create your DBContext with the following override constructor:
public VegaDbContext(DbContextOptions<VegaDbContext> options) : base(options)
{
}
In your start up, you can add your context as a service like this:
services.AddDbContext<ApplicationDBContext>(config => {
config.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
});
You can read in full detail about how dependency injection works here:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection
This part should help you with the migration. You can perform your migrations using the dotnet ef commands https://learn.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet.
When using your db context, do ensure that you are using dependency injection so you make full use of the AddDbContext function and keep it DRY.
https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro
If I were your in your shoes, I look at this document.
Here is the simple DbContext that you can find on this webSite
namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
}
}
}
I just got the same error. If you are careful the error description is actually giving you the solution of the problem.
  DesignTimeFactoryObject's constructor function should not take parameters.
public class ExampleDesignTimeFactory : IDesignTimeDbContextFactory<YourDBContext>{
public ExampleDesignTimeFactory(){ no constructor or no parameter constructor }
}
I use ASP.NET CORE 3.1 to create the project and it solved

Creating a database context using the database first approach with entityframework core.

I want to be able to create a database context with entityframework core in my webapi project using the database first approach.
When I create like this it works very well
public class TestingContext : DbContext
{
public TestingContext(DbContextOptions<TestingContext> options)
: base(options)
{
}
public TestingContext()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=xxxxxx;Initial Catalog=xxxxxx;Integrated Security=False;User Id=xxxxx;Password=xxxxx;MultipleActiveResultSets=True");
}
public DbSet<Information> Information { get; set; }
public DbSet<ArticleUser> ArticleUser { get; set; }
}
I had to add the line services.AddDbContext to make it work.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddCors();
//using Dependency Injection
services.AddSingleton<Ixxx, xxx>();
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddDbContext<TestingContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// Register the Swagger generator, defining one or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "Articles API", Version = "v1" });
});
}
If I remove this method from my TestingContext
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=xxxxxx;Initial Catalog=xxxxxx;Integrated Security=False;User Id=xxxxx;Password=xxxxx;MultipleActiveResultSets=True");
}
I get the error below.
No database provider has been configured for this DbContext.
A provider can be configured by overriding the DbContext.OnConfiguring method or
by using AddDbContext on the application service provider. If AddDbContext is used,
then also ensure that your DbContext type accepts a DbContextOptions object in its
constructor and passes it to the base constructor for DbContext.
Why do I need to pass my connection string to the database in two places before it can pull my data. Please assist. I am new to the core. The two places are configure services method and the context itself.
Option 1: Remove parameterized constructor and OnConfiguring. Result:
public class TestingContext : DbContext
{
public DbSet<Information> Information { get; set; }
public DbSet<ArticleUser> ArticleUser { get; set; }
}
Option 2: Remove parameterized constructor and options in ConfigureServices in AddDbContext
Result:
In Startup.cs
services.AddDbContext<TestingContext>();
In TestingDbContext.cs
public class TestingDdContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=xxxxxx;Initial Catalog=xxxxxx;Integrated Security=False;User Id=xxxxx;Password=xxxxx;MultipleActiveResultSets=True");
}
public DbSet<Information> Information { get; set; }
public DbSet<ArticleUser> ArticleUser { get; set; }
}
Option 3: A parametric constructor is needed to create factory. Example:
public class TestDdContext : DbContext
{
public TestDdContext(DbContextOptions options) : base(options)
{
}
//TODO: DbSets
}
public class TestDbContextFactory : IDbContextFactory<TestDdContext>
{
public TestDdContext Create(DbContextFactoryOptions options)
{
var contextOptions = new DbContextOptionsBuilder();
contextOptions.UseSqlServer("...");
return new TestDdContext(contextOptions.Options);
}
}
If you are creating tests, do you need a backing Sql database? Would the In-memory provider not serve you better?
options.UseInMemoryDatabase("database-name");
For this reason, I'd ditch using the OnConfiguring method, and rely on passing the DbContextOptions to your constructor
Side note, you have to consider what you are testing - are you testing your code that is dependent on your DbContext, or are you testing your DbContext itself - if there is no custom logic and you are merely extending the DbContext, there may not be enough value in writing tests for it - and you're not responsible for testing EFCore itself.