Sharing the Users table between an IdentityDbContext, and a main application DbContext - c#

My application (built in MVC5/EF6) needs to use a single database with two schemas:
identity: To store all the AspNet identity tables for users and roles.
application: To store all my general application tables.
I want to use a separate DbContext for each schema, with the identity one being created with the Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext<ApplicationUser> helper class, and the main application one being created in code with code first. The reason for having two DbContexts like this is so I can put the main application context in a separate assembly and use it in other related projects without having to reference Asp.Net.
However, I want to reference a table in the application schema/context with a foreign key that I want to add to the identity.AspNetUsers table, along with some other extra fields. I then want to create a Users entity in the main context that maps to the identity.AspNetUsers table.
For example, I want an application.Tenants table of which identity.AspNetUsers has a foreign key to, so that I can have many users belonging to a single tenant.
All this is fine I think and will work with no problems, except when it comes to creating the database, and possibly any migrations that affect that table, as I'll have two DbContext's trying to create the same table.
Can I mark a table within OnModelCreating as "do not create", and if so how do I add the foreign key constraint? If not then how do I handle this? I don't think what I'm trying to do is unreasonable. I just want to avoid having two "Users" tables linked with an implied foreign key (i.e. with no actual foreign key constraint).

Why exactly do you want to use two separate DbContexts? It would be easier to have a single context for both ASP.NET identity data and your business entities:
public class DatabaseContext : IdentityDbContext<UserInfo>
{
public virtual DbSet<Entity> Entities { get; set; } // Your business entities
public DatabaseContext()
: base("name=DatabaseContext")
{
}
}
Notice that the DatabaseContext inherits from the IdentityDbContext<UserInfo>.
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.

Related

Asp.Net Core Identity + Clean Architecture

My solution is based on Clean Architecture.
The Domain project should be completely ignorant about the Infrasctrure layer.
The Infrastructure contains a Data Project and an Identity Project.
The Data Project is supposed to implement my repositories. It contains a class called ApplicationDbContext that inherits from DbContext;
The Identity Project is supposed to implement the AspNet Core Identity and all its needs. It contains a class called PortalUser that inherits from IdentityUser and also contains a class called ApplicationIdentityDbContext that inherits from IdentityDbContext;
In the Domain, I have an Entity called User.
User is referenced by several other Entities, like Company (A company has several users).
I'd like to have only one table for both my entities User and the PortalUser.
When I try to apply the migrations, I have several problems referencing User.
What I tried so far:
Create an owned Property called User in PortalUser. But I can't map User in Company entity to an Owned Entity;
Map both User and Portal User to the same table called User, using different DbContexts. But when I apply the migrations to the Database, the migration fails and says that "A table User already exists";
Implement all properties from User in the PortalUser. But when adding a migration it fails and says that other entities like Company can't refer to User.
Make ApplicationDbUser inherit from ApplicationIdentityDbUser but two problems: 1st, it's conceptually wrong to the Clean Architecture; 2nd, The same issues related to having only the PortalUser being created and all other entities referencing User.
I'm stuck on this problem and the project is not going far. All examples that I found so far are raw and don't show what happens when I have navigation properties referencing the User.
The better solution I could think of so far is to have two different tables, one for Identity and another for user needs and references. However, I'm migrating this solution from a messy solution to a more well-organized one, using Clean Architecture. The old version uses only one table for both situations and I can't have a new table and migrate the data.
PLEASE, anyone knows how to solve this problem?

Is there a way to refactor two classes to share a parent class (split table) without losing data?

I have two models, Account and Visitor. Right now they are entirely separate tables, but I recently realized I will need to query for either object type. In other words, I need a super-class which both share (call it User) such that I may query User and receive either an Account or Visitor object.
When I generate the Entity Framework 6 migration, it ends up breaking the database. Specifically:
The shared columns are removed from the child model
No parent (User) entries are created, thus the entries in Account and Visitor become invalid
In the end, the migration fails because the foreign keys created on Account & Visitor are invalid
Right now, the only approach I have is to:
export both child tables via a database dump
run the first half of the migration (no FKs)
manually backfill the data from (1) into the Users class
run the second half of the migration (to add FKs)
Is there a more elegant way to achieve a lossless migration?

Create and use multiple database for single application

I am creating a system which will have multiple customer. right now i am using same database and table for all customer but i think it'll slow down fetching of record when i'll have hundreds of customer's data in same database.
so should i create separate database for each new registered customer dynamically by executing scripts from code? (will use master database to manage all user's connectionstrings)
I'm using entity framework. so same will be possible using EF? will it cause any problem?
May be you can use ABP framework to handle multiple database with entity framework.
ABP will help you to auto register repositories into IocContainer by adding attribute of all your DBContext (Each DBContext connect to a DB) as following:
[AutoRepositoryTypes(
typeof(IRepository<>),
typeof(IRepository<,>),
typeof(SimpleTaskSystemEfRepositoryBase<>),
typeof(SimpleTaskSystemEfRepositoryBase<,>)
)]
public class SimpleTaskSystemDbContext : AbpDbContext
{
...
}

Will migrations affect my database?

I am learning Entity Framework to query the database of my company. I have an ASP.NET MVC project and as of now, I have established a connection to the company's principal server database. That has given me access to all the tables and I created a separate class Library containing all the corresponding POCOs(generated automatically).
In the tutorial I was following they say to use "enable-migrations" to have the database updated with the model.
So does that mean that if I were to modify the models in my project, that would have a direct effect on the database? Since I am new to this project I do not want to do anything stupid, like altering the database. For now I just want to query the database and retrieve information, then use that information to show more or less information on a web page.
EDIT: Just as an example, I would like to show a difference between the model generated by EF and what my real table looks like. I have a table Web_Profils that contain and ID, a ProfileName and an Order (int). This DB has no primary keys or foreign keys. If there are relations, they are defined through new tables. But when EF generates all my classes, it adds ICollections, for example in Web_Profils, I have a.o virtual ICollection<Web_User_joint_Profils>Web_User_joint_Profils which is not present in the actual table, it just seems to be the relation that EF has deduced(it is the relation between Users and Profiles present in the table Web_User_joint_Profils). Now, will doing a migration affect my tables just because EF has added these collections in my model?
I've also read that it is possible to deactivate migrations using :
Database.SetInitializer(new ContextInitializerNone<YourDbContext>());
Any thoughts?
If you update your model, you need to add a migration to your project and update your database with that migration.
Unless you do those steps after updating your model, changes will not be reflected in the database.

Accessing ApplicationUser for foreign key without reference to Entity Framework

I have divided my ASP.NET MVC 5 project into two distinct projects/assemblies:
MyProject.Entities
and
MyProject.Web
Where .Entities contains my business/domain logic (basically model classes for my custom data objects) and .Web contains the actual ASP.NET MVC framework and web infrastructure.
I am basing this design off of Scott Allen's excellent ASP.NET MVC 5 Fundamentals course where he explains how it separates the business logic from the web infrastructure.
However I've run into a problem which Scott only briefly addresses: accessing ApplicationUser in my .Entities classes.
I want my data entity's table to contain a foreign key pointing to a specific ApplicationUser for each entry. But because ApplicationUser inherits from IdentityUser, I would need a reference to AspNet.Identity.EntityFramework.
Scott says that "isn't going to work for a lot of people", and is "rather distasteful". He says that I would have to implement my own UserStore or UserManager to utilize it.
I believe that is vastly overkill for simply wanting to be able to foreign key ApplicationUser in a few tables.
I can get the foreign key column in question into my data table by creating a navigational property in the ApplicationUser class in IdentityModel like so:
using MyProject.Entities;
public class ApplicationUser : IdentityUser
{
public virtual ICollection<Request> Requests { get; set; }
}
and then doing a simple Entity Framework migration. However, I can't explicitly access the user through my object.
So:
Why would it be "distasteful" to reference Entity Framework in my business/domain layer, and
How can I get a foreign key reference declared in that layer to ApplicationUser where I need it?

Categories