Entityframework : DropCreateDatabaseAlways, where and how? - entity-framework

I am working with Entityframework Code-First and trying to get my tables to drop and then recreate at every startup. However Database.SetInitializer is not recognized and intellisense is not giving me a using directive. Hovering over setinitializer gives the following information:
DatabaseFacade does not contain a definition for 'setinitializer'....
And my Applicationdbcontext below.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
Database.SetInitializer<ApplicationDbContext>(new DropCreateDatabaseAlways());
}
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);
}
//dbsets
}
}
Am i implementing 'Database.SetInitializer' in the wrong place? Why am i not getting any using directive information from intellisense?

Related

ignore one table with ef-core migration

I have an ASP.NET Core application. I have structured the application as multiple projects under the solution. In two of the projects I have 2 different contexts for the same database. The problem is I have a table I am using for auditing in both contexts, and this is causing a problem with migration.
My question is:
is there anyway I can make migration ignore creating this table in one of the contexts?
I am getting the error in the following line:
dbContext.Database.Migrate();
in you dbContext you can ignore one or more table using model builder ignore and give the entity class type you want to ignore
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Ignore<YourClassHere>();
}
You can do this by adding onModelCreating method.
public class ApplicationDbContext : DbContext
{
public DbSet<TableName> TableNames { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TableName>().ToTable(nameof(TableNames), t =>
t.ExcludeFromMigrations());
}
}

ASP.Net.Core 2.2 Identity change ID from string to int

I'm trying to change the ID of the Users table from a string (GUID) to an int and really struggling. I have looked at lots of examples but they seem to be for earlier versions of Identity or vs and for numerous reasons they don't work.
I either get a compiler error
'Microsoft.AspNetCore.Identity.IdentityUser', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStore 6[TUser,TContext,TKey,TUserClaim,TUserLogin,TUserToken]' violates the constraint of type 'TUser'.
Or when I create the migration I still get a string column for the ID not an int as I was expecting.
I'm using vs2019. Asp.Net.Core 2.2 and Microsoft.AspNetCore.Identity 2.2
Can anyone help me out, please? Thanks!
First extend the IdenityUser class class as follows so that you can add custom properties:
public class ApplicationUser : IdentityUser<int>
{
}
Then extend the IdentityRole class follows if you use Role in application too. You can keep this safely even you don't want to use it:
public class ApplicationRole : IdentityRole<int>
{
}
Now your ApplicationDbContext should be as follows:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
Now in your ConfigureServices method of the Startup class as follows:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
}
Job done! Now run a brand new migration and apply it.
#TanvirArjel solution also worked with .NET Core 3.1 in my project with modifications. I had added Identity through scaffolding.
Instead of editing ConfigureServices(), I edited IdentityHostingStartup.cs instead and mofified Configure() inside IdentityHostingStartup.cs:
builder.ConfigureServices((context, services) =>
{
services.AddDbContext(options => options.UseSqlServer(context.Configuration.GetConnectionString("IdentityDbContextConnection")));
services.AddIdentity()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders()
.AddDefaultUI(); //add default razor pages for identity (login, register, etc)
});

Unable to query new table from asp.net core web application using EF 1.0

I have developed a new asp.net Core web application using Visual Studio 2015. I am at the point where I am adding user customization options by adding additional tables to my local database. However I have been unable to add whatever EF needs to query a new table correctly. I get the following error when attempting to query the table..
Applying existing migrations for ApplicationDbContext may resolve this issue
There are migrations for ApplicationDbContext that have not been applied to the database
•00000000000000_CreateIdentitySchema
Apply Migrations
In Visual Studio, you can use the Package Manager Console to apply pending migrations to the database:
PM> Update-Database
Alternatively, you can apply pending migrations from a command prompt at your project directory:
dotnet ef database update
My table is a simple table with a few varchar or nvarchar columns. The model looks something like...
namespace MyNamespace.ColorSchemes
{
public class ColorSchemesViewModel
{
[Required]
public string Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string bc { get; set; }
}
Table looks something like this in SQL Server...
CREATE TABLE [dbo].[ColorSchemes](
[Id] [nvarchar](50) NOT NULL,
[Name] [varchar](32) NOT NULL,
[bc] [nchar](7) NOT NULL
)
I have added the table to the application context like such...
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<ColorSchemesViewModel> Colors { get; set; }
I have also used as separate class similarly like..
public DbSet<ColorSchemes> Colors { 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);
}
}
I have added the context to a controller like this...
private ApplicationDbContext _context;
public MyController(IMemoryCache memoryCache, ILoggerFactory loggerFactory, ApplicationDbContext context)
{
_memoryCache = memoryCache;
_logger = loggerFactory.CreateLogger<ChordMVCController>();
_context = context;
}
I have tried to query the table in my controller like this...
var colorSchemes = (from c in _context.Colors
select c).ToList();
I have attempted to use the Package Manager to per instructions from the error...
PM> Update-Database
I always get this error...
System.Data.SqlClient.SqlException: There is already an object named 'AspNetRoles' in the database.
This doesn't make sense since this table is already in the database and the EF definition. How do I get my table added properly to the EF migrations so I can query it?
I was able to solve this myself...
I created a different context rather than trying to embed the dbset in the default ApplicationDbContext and also removed the onModelCreating method.
public class ColorSchemeDbContext : DbContext
{
public ColorSchemeDbContext(DbContextOptions<ColorSchemeDbContext> options) : base(options)
{
}
public DbSet<ColorScheme> ColorSchemes { get; set; }
}
Replaced the ApplicationDBContext with the new context in my controller class...
private readonly ColorSchemeDbContext _context;
public MyController(IMemoryCache memoryCache, ILoggerFactory loggerFactory, ColorSchemeDbContext context)
{
_memoryCache = memoryCache;
_logger = loggerFactory.CreateLogger<ChordMVCController>();
_context = context;
}
After that the query worked. I spent a lot of time attempting to use the EF migrations to create the tables from a class syntax. Nothing seemed to work. I was creating a new .NET CORE web application in VS 2015 with the template and using user authentication which creates the AspNetRoles tables in SqlLite once you do an update-database. It is very confusing how to add additional tables using a code first approach after that. A lot more documentation is needed regarding EF migrations with respect to managing projects over time. I see the benefits of having all of your database updates maintained from your VS project but it is not easy to understand.

Unable to add DbModelBuilder and .HasRequired() to modelBuilder

I am trying to create a ModelBuilder within my API and can't seem to add .HasRequired() to my code. I am assuming this is due to the fact that it lives within DBModelBuilder, however, I cannot add that also.
It will only allow me to use ModelBuilder.
Otherwise it throws an error: OnModelCreating(DbModelBuilder): no suitable method found to override
Am I missing something here?
My DbContext looks like so:
public class TicketContext : DbContext
{
public DbSet<Tickets> Tickets { get; set; }
public DbSet<Users> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) // <-- Not allowing me to add DbModelBuilder here
{
modelBuilder.Entity<Tickets>().HasRequired(t => t.Users);
}
}
Update
I have (as a test) started a new project from scratch. I created a new ASP.NET 5.0 project using a Web API template. Straight away my project doesn't recognize DbModelBuilder. I added reference to EntityFramework.dll and still no good. I then added using System.Data.Entity; and it then accepted DbModelBuilder but still complains that the namespace 'DbModelBuilder' could not be found.
I can't understand how I can have this error upfront on a brand new project?
As soon as I try and add the package Entity Framework from NuGet, I get more errors that version 6.1.3 is not compatible with DNX Core 5.0
I can't seem to find any examples/solutions to any of these errors.
Update 2
I have managed to get DbModelBuilder recognized now by adding the EntityFramework.dll reference to the DNX Core 5.0 Assembly as well as the DNX 4.5.1 assembly, however, now it has thrown even more errors wanting System.Core added and mscorlib. I really can't believe how much trouble it is to create a (what I thought would be simple) Web API project.
You can't just call HasRequired off the model builder - you need to indicate the entity you want to change:
public class MyContext: DbContext
{
public DbSet<Foo> Foos { get; set; }
public DbSet<Bar> Bars { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Foo>().HasRequired(f => f.Bar); // assumes Bar navigation added to Foo
}
}
https://msdn.microsoft.com/en-us/data/jj591617.aspx?f=255&MSPPError=-2147217396
What I like to do is separate out my fluent code like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new FooConfig());
}
Now I can create a class with all my mapping for that entity:
public class FooConfig : EntityTypeConfiguration<Foo>
{
public FooConfig()
{
// Primary Key
this.HasKey(t => t.FooId);
// Relationships
this.HasRequired(f => f.Bar).WithMany(b => b.Foos);
}
}

How do I singularize my tables in EF Code First?

I prefer using singular nouns when naming my database tables. In EF code first however, the generated tables always are plural. My DbSets are pluralized which I believe is where EF is generating the names but I don't want to singularize these names as I believe it is more pratical to have them plural in code. I also tried overriding the setting but to no avail.
Any ideas? Here is my code and thanks.
MyObjectContext.cs
public class MyObjectContext : DbContext, IDbContext
{
public MyObjectContext(string connString) : base(connString)
{
}
public DbSet<Product> Products {get;set;}
public DbSet<Category> Categories {get;set;}
//etc.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingEntitySetNameConvention>();
}
}
You've removed the wrong convention (PluralizingEntitySetNameConvention) for this purpose. Just replace your OnModelCreating method with the below and you will be good to go.
using System.Data.Entity.ModelConfiguration.Conventions.Edm.Db;
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
With Entity Framework 6, on your file that inherit from DbContext:
using System.Data.Entity.ModelConfiguration.Conventions;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
You can also change the property value:
On the Tools menu, click Options.
In the Options dialog box, expand Database Tools.
Click O/R Designer.
Set Pluralization of names to Enabled = False to set the O/R Designer so that it does not change class names.
Set Pluralization of names to Enabled = True to apply pluralization rules to the class names of objects added to the O/R Designer.
The location of the definition of PluralizingTableNameConvention has moved to:
using System.Data.Entity.ModelConfiguration.Conventions;