No parameterless constructor was found on 'TContext' - c#

I am not really clear on why the error happens. When I first scaffold my project the migration and update-database commands ran fine but after few changes in the application I was getting this error. The only solution floating around is this:
public class BloggingContextFactory : IDbContextFactory<BloggingContext>
{
public BloggingContext Create()
{
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlite("Data Source=blog.db");
return new BloggingContext(optionsBuilder.Options);
}
}
My DbContext:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
public DbSet<ApplicationUserCode> ApplicationUserCodes { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}
It works for me but the connection string is hard-coded inside the class which is not fine with me. Any clarifications as to why this error did not happen at one time and later it did is really appreciated and also a elegant solution than embedding connection string in class please.

did you have this
public class BloggingContext : DbContext
{
public BloggingContext(){ // << The reason....
}
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
}
Another reason is that it was seeing the OnModelCreating(ModelBuilder builder){} override without the base.OnModelCreating(builder); call inside the OnModelCreating(){} method at the top of the method itself. Threw me for a loop as to why... then I tried a few things, low and behold it was a simple inclusion of the parameterless constructor it was looking was the culprit.
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder); //<< Absolutely required at the top.
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
EDIT
//Startup.cs ConfigureServices(IServiceCollection services)
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("SqliteConnection")));
//appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=(LocalDb)\\MssqlLocalDb;Initial Catalog=PilotSystemCore;Integrated Security=True",
"SqliteConnection" : "Data Source=SqliteDbName.db"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
NB: If you did any migrations with SqlServer before, the generated items are long valid redo the migrations.

Related

I can not add migration when I want add Identity to my project in ASP.NET Core

I want to use identity in my project. I did create identity DbContext and also I did add Identity services to my startup file
But when I want create a new migration I see this error:
Unable to create an object of type context name for the deferent design patterns supported at design time
My context code here:
public class websitecontext : IdentityDbContext
{
public websitecontext(DbContextOptions<websitecontext> options) : base(options)
{
}
}
My startup codes here
services.AddDbContext<websitecontext>(s =>
s.UseSqlServer(Configuration.GetConnectionString("websiteconnectionstring"))
);
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<websitecontext>()
.AddDefaultTokenProviders();
Please helps me I did search in google but I didn't find any results
I solved the problem
I did add seed data in my context but I did not pass this to identity dbcontext and now I did pass this with :
base.OnModelCreating(modelBuilder);
I Resolved this by just adding a plain constructor to my Context
public class DataContext : DbContext
{
public DataContext()
{
}
public DataContext(DbContextOptions options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
if (!options.IsConfigured)
{
options.UseSqlServer("A FALLBACK CONNECTION STRING");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}

Dependency Injection with configuration in .net core

I am trying to inject dependency by getting configuration in class in .net core project. The class where I am trying to inject dependency is in another project. But somehow I am not able to get the values from config file in injected dependency.
Below is my code
In below DBContext I need to obtain value from configuration, where i have used DI of DBConfiguration class.
public class DBContext : DbContext
{
private readonly DBConfiguration _dBConfiguration;
public DBContext(DBConfiguration dBConfiguration)
{
_dBConfiguration = dBConfiguration;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_dBConfiguration.ConnectionString);
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
And my StartUp.cs file in web api
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<DBConfiguration>();
services.AddEntityFrameworkSqlServer().AddDbContext<DBContext>();
services.AddOptions();
services.Configure<DBConfiguration>(Configuration.GetSection("DBConfiguration"));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
and my appsettings.json file
{
"DBConfiguration": {
"ConnectionString": "Server=myserver;Database=BaseProjectDB;Trusted_Connection=True;MultipleActiveResultSets=true",
"ApplicationName": "WebAPI"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
Any help on this appreciated !
You seem to be using DBConfigurationOptions in your StartUp file, while you're injecting DBConfiguration in your DBContext.
This is how I currently use my configuration:
public class Startup
{
private readonly IConfiguration _configuration;
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
_configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<DBConfigurationOptions>(_configuration.GetSection("DBConfiguration"));
}
}
and then it's injected as:
public class DBContext : DbContext
{
private readonly DBConfigurationOptions _dBConfiguration;
public DBContext(IOptions<DBConfigurationOptions> dBConfiguration)
{
_dBConfiguration = dBConfiguration.Value;
}
}
Why don't you configure the db directly in the place you also have the configuration?
In your DBContext class (btw you should probably choose a better name for that) you just need to expose a constructor like this, no need for overriding OnConfiguring or anything like that.
This class can be in any assembly you want.
class DBContext : DbContext
{
public DBContext(DbContextOptions<DBContext> options) : base(options)
{
}
}
For the configuration you can just use the built in optionsBuilder-action (place inside the ConfigureServices method):
services.AddEntityFrameworkSqlServer()
.AddDbContext<DBContext>(optionsBuilder =>
optionsBuilder.UseSqlServer(
Configuration.GetSection("DBConfiguration").Get<DBConfiguration>().ConnectionString)
);
Currently the way you get the configuration can definitely be improved. For example you could do something like this:
var DBConfig = Configuration.GetSection("DBConfiguration").Get<DBConfiguration>();
services.AddSingleton(DBConfig);// <- now you can inject that if you want but it's not necessary
// now we don't need to get the config here
services.AddEntityFrameworkSqlServer()
.AddDbContext<DBContext>(optionsBuilder =>
optionsBuilder.UseSqlServer(DBConfig.ConnectionString)
);
There are some other things you might want to improve like better naming for DBContext and not overriding members you don't have a specific implementation for (like you did with OnModelCreating).
Also for a next time you should include all the classes that aren't part of some sort of public API like your DBConfiguration class.
To receive the configuration, you have to modify the signature of your constructor in DBContext from
public DBContext(DBConfiguration dBConfiguration)
to
public DBContext(IOptions<DBConfiguration> dBConfiguration)
to receive the option properly (don't forget to add the namespace Microsoft.Extensions.Options).
Additionally, you need to define the DBConfiguration class somewhere with the properties you have in your configuration file.

EF won't create empty database

I'm trying to create a database through EF, to store members and their locations.
I've had a look at other examples, but no matter what I do, when I run my program, my database doesn't get created.
I've noticed that the example I followed created a DataInitializer class, which puts some records in the database. I haven't done this yet, since I would like to check if my database gets created with the right columns.
Could not having data in the database be the problem?
public class ApplicationDbContext : DbContext
{
public DbSet<Lid> Leden { get; set; }
public DbSet<Locatie> Locaties { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfiguration(new LidConfiguration());
builder.ApplyConfiguration(new LocatieConfiguration());
}
}
Appsettings.json:
{ "ConnectionStrings": {
"DefaultConnection": "Server=.\\sqlexpress;Database=Taijitan;Trusted_Connection=True;MultipleActiveResultSets=true"},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
In the example I followed, startup.cs also contains
services.AddScoped<BeerhallDataInitializer>();
and all the way at the bottom
beerhallDataInitializer.InitializeData();
I don't suppose this is what's causing the problem, but I'm not so sure anymore
EDIT:
public class BeerhallDataInitializer
{
private readonly ApplicationDbContext _dbContext;
public BeerhallDataInitializer(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public void InitializeData()
{
_dbContext.Database.EnsureDeleted();
if (_dbContext.Database.EnsureCreated())
{ *create new objects and add them to _dbcontext*
_dbContext.SaveChanges();
}
}
In order to run a migration you first need to create the migration with the command:
'dotnet ef migrations add InitialCreate'
Secondly, then you need to run your migration with the command:
'dotnet ef database update' or by creating some code that run missing migrations which i can assume it's what beerhallDataInitializer.InitializeData() does but can't know for sure since I have no more information about it but to be able to migrate via code you need the reference to the IApplicationBuilder like so in the startup.cs file:
DbInitializer.Migrate<ApplicationDbContext>(app);
and my dbinitilizer is :
public static class DbInitializer
{
public static void Migrate<T>(IApplicationBuilder app) where T : DbContext
{
using (var scope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
scope.ServiceProvider.GetRequiredService<T>().Database.Migrate();
}
}
}
Hope it helps anything just comment bellow but give more information about what you have done
Edit:
try changing your connection string to:
Data Source=localhost\\SQLEXPRESS;Initial Catalog=Taijitan;Integrated Security=True

AddDbContext was called with configuration, but the context type 'ContextClass' only declares a parameterless constructor?

Detail
I am trying to create asp.net core application and use scaffold-dbcontext to generate class. when I run this app it shows me the error. I already follow some answer on stackoverflow with the same issue but mine remains. Question
MyContext
public partial class MyContext: DbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
}
public virtual DbSet<Answer> Answer { get; set; }
public virtual DbSet<Attachment> Attachment { get; set; }
public virtual DbSet<Category> Category { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(#"Server=.;Database=MyContext;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder) { .... }
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddMvc()
.AddJsonOptions(options =>
options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.All);
services.AddDbContext<MyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
Error
AddDbContext was called with configuration, but the context type 'MyContext ' only declares a parameterless constructor. This means that the configuration passed to AddDbContext will never be used. If configuration is passed to AddDbContext, then 'MyContext ' should declare a constructor that accepts a DbContextOptions and must pass it to the base constructor for DbContext.
in appsetting.json file
declare your connection string with name "DefaultConnection"
"Data": {
"DefaultConnection": "Data Source=(local); Initial Catalog=DBname; Integrated Security=True"
}

How to use IdentityDbContext

For the last few days, I have been playing around with Asp.net's Identity framework.
I have been able to get the Register and Login working however when I try to extend the functionality to saving data against specific users, I find it is different to how I would normally implement it with stock standard EF.
Normally I would use something like below to save data:
using(var context = myDbContex())
{
context.Add(object);
context.SaveChanges();
}
However, when I try to use this approach after inheriting the IdentityDbContext it is expecting an argument. Is it okay for me to create a default constructor that doesn't take any arguments or should I be passing something in?
My Context currently looks like this:
public class AppContext : IdentityDbContext<ApplicationUser>
{
//I am not really sure why options needs to be specified as an argument
public AppContext(DbContextOptions<AppContext> options)
: base(options)
{
}
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Xxxxx> Xxxxx { get; set; }
public DbSet<Yyyyy> Yyyyy { get; set; }
public DbSet<Zzzzz> Zzzzz { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppContext>(options =>
options.UseSqlite("Data Source=App.db"));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<AppContext>()
.AddDefaultTokenProviders();
});
Why is this implementation of the context different to the standard dbContext, and how can I save data using this context?
Thanks
Because of this line
services.AddDbContext<AppContext>(options => options.UseSqlite("DataSource=App.db"));
You need to provide a constructor that has the DbContextOptions as paramter, which has nothing todo with IdentityDbContext.
You have two choices now.
Use dependency injection, that is how you are supposed to use it anyway
public class MyController : Controller
{
private AppContext context;
public MyController(AppContext context)
{
this.context = context;
}
}
Secondly you could register your context differently.
services.AddDbContext<AppContext>();
And apply changes in your context, remove the constructor and override OnConfiguring(DbContextOptionsBuilder optionsBuilder)
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=App.db");
}
Now you can use it as you usually would do.
using(var context = new AppContext())
{
// do stuff
}
EDIT:
Not part of the actual question but signin, registration and role managing is handled by these classes, that can be injected when using IdentityDbContext
SignInManager
UserManager
RoleManager

Categories

Resources