I have an application which uses EntityFramework edmx models and i want to be able to use the same dbContext for my Identity classes and the entity classes. Someone has raised a Similar Query but i am unable to get them to be compatible.
ive changed the class definition in the EF context class as below
public partial class MyDbContext : IdentityDbContext<AspNetUser>
{
}
and my identity user as
public partial class AspNetUser : IdentityUser
{
}
but i get an error when i try to login or register
The entity type AspNetUser is not part of the model for the current
context
The solution I came up with recently is to use single context for both ASP.NET identity data and your business entities:
public class DatabaseContext : IdentityDbContext<UserInfo>
{
public virtual DbSet<Comment> Comments { get; set; } // Your business entities
public DatabaseContext()
: base("name=DatabaseContext")
{
}
}
Notice that the DatabaseContext inherits from the IdentityDbContext.
There are some trade-offs with this approach: for example, your data access layer should reference Microsoft.AspNet.Identity.Core and Microsoft.AspNet.Identity.EntityFramework; however, having a single database context in your project makes things much easier if you are using dependency injection or Entity Framework migrations.
I recommend using those dbContext separate, due to async nature of how identity works. You want to have absolute control over your application context.
For that reason I usually inject the identity dbContext by using the same connection from the application context, but there are two separate instances.
Also if you ever wanted to have your application dbContext anything other than code first it will not be possible to merge with the identity dbContext.
Related
I am new to fairly new to programming and started a new project using asp.net core and MVC.
Since i wanted to see what was going on behind the scenes, i implemented authentication and authorisation manually using IdentityUser and IdentityDbContxt.
During the initial migration, a bunch of tables were created that allows the users to register and then login in. I have implemented all of that.
Now I want to create a new table within the same database that will let the users submit their names and address. I believe i can just create a new table using sqlite GUI and work with that, but how do I create a UserProfileModel.cs file and have that schema show up on the database?
My apologies if my question is not very clear. Also , I am working with microsoft stack on a mac :).
Thanks.
First of all, you can always extend the IdientityUser, add migration, update the database and names and addresses will be added to the table.
public class UserProfileModel:IdentityUser
If you want to have more models with tables, you have to make a class that extends the IdentityDbContext, pass the db options to the constructor and add your DbDets, wich will be use for creating the tables.
public class AppDbContext : IdentityDbContext<User>
{
public DbSet<UserProfileModel> Residences { get; set; }
public AppDbContext (DbContextOptions<AppDbContext> options) : base(options)
{
}
Then, where you configure the services you have to add the database,
services.AddDbContext<AppDbContext>(options => options.UseSqlite(configuration.GetConnectionString("Your Connection String")));
I assume you have already made that, maybe with IdentityDbContext, but you can add your custom DbContext.
Now you can inject your AppDbContext wherever you want to use it. Probably to a service or a repository.
I installed nuget packages for asp.net identity and followed this MS tutorial which, by creating a new user, creates all of the tables e.g. AspNetRoles, AspNetUsers in my database.
The problem is, I'm trying to use CodeFirst migrations for DB source control and my Visual Studio side has none of the models for these tables. I don't want the "Create user" method to automatically create the tables, I need to get my models in Visual Studio and then push it using a migration.
Currently I have all the [AspNet] tables in my database and no reflection of this in my migrations. I can delete the tables but need to know how to populate the code first!
I'll also probably need to customise the models later, but that's another issue.
You can extent your asp.net identity as bellow
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Employee> Employees { get; set; }
public DbSet<Attendance> Attendances { get; set; }
public DbSet<PunchRecord> PunchRecords { get; set; }
}
Took me two hours to find I simply needed to add a model that inherits IdentityUser and then add a migration. I've called the model "ApplicationUser" - based on a tutorial I found on how to extend AspNetRoles and an answer somewhere in stackoverflow, it seems this name is possibly automatic or scaffolded somewhere... but I just chucked it manually in my Models folder:
public class ApplicationUser : IdentityUser
{
}
Also, I had to tinker with my application's context to inherit from IdentityDbContext - this way I don't need two separate connection strings and my app context is now all inclusive.
I'm using the code first pattern to creating DB. I already have a DbContext/DB setup. Now I decided to add auth support to it using Identity.EntityFrameworkCore.
I've created another DbContext to have the identity related tables like below :
public class AccountDbContext:IdentityDbContext
{
public AccountDbContext(DbContextOptions<AccountDbContext> options) : base(options)
{
}
}
I've added the above DbContext in startup.cs as below :
services.AddDbContext<AccountDbContext>(o => o.UseSqlServer(Configuration.GetConnectionString("TESTDB")));
And finally :
dbContext.Database.EnsureCreated();
But since TESTDB is already associated with an existing db context, its already created. So I guess the function call - EnsureCreated() would do nothing and simply return.
My questions:
Is there any way to avoid creating a duplicate context for IdentityContext and somehow add it to my existing DB Context ?
If I do go about a separate DbContext like above (but using the same existing DB) how to ensure the Identity/roles tables are auto created ?
You can avoid to create two context by extending the AccountDbContext in your default DbContext.
public class YourDbContext : AccountDbContext
{
}
OK, found a solution. I can directly inherit the IdentityDbContext instead of DbContext (since IdentityDbContext extends DbContext anyway). Migrations can be added as usual.
I added a database to my project, then I want to add a controller.
When the Add Controller window pops up, I am asked to choose Data context class.
Surprisingly, I found that there are 2 context classes:
One is called: my_database_name_dbEntities(projectname)
Another one is called:
ApplicationDbContext(projectname.Models)
which is what I created when I added the Entity Framework object which connects to my database.
I am confused about
which one to use
what are the differences
Here is the screenshot
Update
I tried both of them and here is what I have got:
If I choose the databasename_dbEntities, VS generates views and controller perfectly with no problems.
If I choose ApplicationDbContext, VS throws an error:
Error
There was an error running the selected code generator:
'Unable to retrieve metadata for 'lrc.Event'. One or more validation
errors were detected during model generation:
AspNetUserLogin: : EntityType 'AspNetUserLogin' has no key defined.
Define the key for this EntityType.
AspNetUserLogins: EntityType: EntitySet 'AspNetUserLogins' is based on
type 'AspNetUserLogin' that has no keys defined.
'
Update
Now, I changed the super class from DbContext to IdentityDbContext for the projectname_dbEntities.
So it looks like this now:
public partial class projectname_dbEntities : IdentityDbContext<ApplicationUser>
{
public projectname_dbEntities()
: base("projectname_dbEntities", throwIfV1Schema: false)
//: base("name=projectname_dbEntities")
{
}
public static projectname_dbEntities Create()
{
return new projectname_dbEntities();
}
.....
}
I wonder :
what are the advantages of using the the derived class from IdentityDbContext over the DbContext?
Out of the box, when you create an ASP.NET MVC 5 project using the default template in Visual Studio 2013, you get a basic, ready-to-run website with the elementary Identity and Account management classes already in place.
There is a class ApplicationDbContext. This is the Entity Framework context used to manage interaction between your application and the database where your Account data is persisted (which may, or may not be the same database that will be used by the rest of our application) and this class inherits from IdentityDbContext.
IdentityDbContext is basically a regular DbContext with two DbSets. One for the Users and one for the Roles.
If you don't want use ASP.NET Identity, you can ignore it or mix it into your own DbContext class.
I stumbled uppon the same problem as described in this question. In addition, i didn't want to loose the __migrationHistory table from the database.
I tried it with the suggested Solution of using one "super" context which contains all DbSet<>s and using the normal Contexts, but i got a error. ("Model backing DbContext has been changed")
This is easily avoidable if you just kill the __migrationHistory table from the SQL server, but as i said, i want to keep the history.
I found a simple and easy solution, see my answer below.
First, you have to create a "Super" Context for the Migrations Configuration.
MySuperContext : DbContext
{
// All DbSet<> s from your different contexts have to be referenced here once, you will only use this class for the migrations.
public MySuperContext() : base("YourConnectionString")
{
System.Data.Entity.Database.SetInitializer(new MigrateDatabaseToLatestVersion<MySuperContext, MyMigrationsConfiguration>());
}
}
Then just create the following class:
public class NoDatabaseInitializer<T> : IDatabaseInitializer<T> where T: DbContext
{
public void InitializeDatabase(T context)
{
// Do nothing, thats the sense of it!
}
}
now, in every small Context you have, add this to the constructor:
class MyUserContext : DbContext
{
public MyUserContext : base("MyConnectionString") // Can be a user context, etc
{
System.Data.Entity.Database.SetInitializer(new NoDatabaseInitializer<MyContext>());
}
}
now you won't get this error any more,
plus, you will have your migration-History,
and you will use multiple Contexts on one Database.
EF6 supports multiple DbContexts per database: http://entityframework.codeplex.com/wikipage?title=Multi-tenant%20Migrations