Asp.Net Core Identity + Clean Architecture - c#

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?

Related

Is it possible to have multiple Identity-Instances in the same DBContext?

We have an existing ASP.net Core 2.1 Application which has UserAccounts associated with the Identity-System.
Now we would like to add Admin-Users which shall not share the UserAccountsTable which is already used by the UserAccounts. (Yeah i know, we could simply add a bool column like isAdmin but we opted for seperated tables).
So my thinking was, that i need to create a new Identity-Instance which is using our AdminUser and AdminRole classes (Both deriving from IdentityUser and IdentityRole accordingly).
In the DBContext i can now change the Table-Names via the Fluent-API of AdminUser and AdminRole. But how would i now change the names of the needed "infrastructure" tables created by Identity automatically?
I've found this documentation by Microsoft. But they are only using "generic" types to rename the tables for e.G. the Link-Table between Users and Roles (IdentityUserRole). This type would probably "conflict" with my already configured UserAccounts-Identity, therefore "renaming" both tables, making troubles again, or not?
An obvious solution could be to create a new AdminUserContext, which would not share the UserAccounts-Information. But then we would lose the Links to the Entities we actually would want to administrate? And linking DBContexts doesn't feel "right" to me.
Anybody got some ideas to this?

Extending Entity Framework Models for SAAS

I am building an asp.net mvc application that is using Entity Framework 6. We have the challenge of building several implementations of this same application. So we have created a core library called MyApp.Core which contains the following:
DbContext
Models
Customer
Product
(other models)
Repositories
We have the need to extend models for different implementations of the application. For example we might want to put SomeProperty on the customer table for 1 customer and SomeOtherProperty for another customer.
How can we improve the structure so it doesn't break the EF code first migrations? Or cause any other issues?
Should we just have a unique ASP.net project for each customer that references the MyApp.Core? And should we reference those via a nuget package? Or something else like a git sub module?
Any suggestions on the organization of the custom implementations of this type of structure?
Your solution may be an IsA (Is-a, is a) database structure that can be created from your code-first model using the TPC method mentioned here:
http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines
You might create an abstraction such as ICustomer, or CustomerBase which contains a reference to a table containing the implementations of your application (is that Product?).
You might also transform your Customer class into a base class, and other classes with additional fields would inherit from it.
In either event, the article deals with bringing code first into a database model that can handle this kind of thing. You may also want to take a look at multi-tenant architecture, just to say you've done your homework. That's here: https://msdn.microsoft.com/en-us/library/aa479086.aspx

How to use Entity Framework code-first with a newer database model version

Maybe an odd question, but we have a scenario in which we want to use Entity Framework code-first in an environment which could have a database with a newer/higher version than the code itself.
Let me elaborate a bit. We have a couple of solutions which all use a core assembly which contains the overall datamodel which all solutions are using. The solutions are mainly sites and apps which are deployed to several different Azure Web Sites. So the solution are running next to each other. The only thing they are sharing is the Azure database.
Now the scenario will come in play. When we update the database model in the core assembly and update one of the solutions in Azure. The underlying database will be updated when the model is loaded within that solution. No problem there, works like a charm...
The problem starts when one of the other solutions is loaded. These other solution are still using the previous core assembly which has now an outdated EF CF model compared to the database model they are connecting with. So a nice exception will be throw as shown below.
The model backing the '{NAME}' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data.
The question is whether we can force the model just to load and ignore the changes made within the database. We internally have a policy to only apply not breaking changes within the database, so the model should be able to load without any problems.
Thanks in advance for the information and tips!
I can be wrong(not sure whether I remember correctly), but if it doesn't interferes with your application configuration, you can set DB initializer to null:
public PortalDbContext()
: base("name=PortalConnectionString")
{
Database.SetInitializer<PortalDbContext>(null);
}
Or it could be possible to create custom initializer:
public class BlogContextCustomInitializer : IDatabaseInitializer<BlogContext>
{
public void InitializeDatabase(BlogContext context)
{
if (context.Database.Exists())
{
if (!context.Database.CompatibleWithModel(true))
{
// Do something...
}
}
}
}
If you're using EF Code-First, the model must match the database.
Even if you found a way to circumvent that limitation you'd be doing something dangerous.
Let me expalin it: if you update the database from "Solution A", the model in "A" will match the database, and any further changes to the model in this solution can be applied to the database without any problem at all. That's right!. However, if you do what you're asking in this question, i.e. you do something so that "Solution B" can keep working even if the model doesn't mathc with the DB, and then you make a change to the model in "Solution B", how do you apply it? how can "Solution B" know what changes to apply? how can "B" determine what changes made by "A" should be left as they are, and what are the new changes made by "B" that must be applied to the database?
If you could follow on like this, you'd finish with two different code first models, none of which matches the database, and, besides, how could you warranty that both applications work correctly? how can you ensure that changes on "A" doesn't affect code on "B" and viceversa?
The safest solution to avoid this problem is to share the assembly containing the code first model between both solutions. Any other solution will be troublesome sooner or later. Perhaps you'll have to refactor your solutions so that they can share the same DbContext. The DbContext must be the only thing in your project. I usually have an Entities project, and a DbContext project which has a reference to Entities. Then both solutions would have references to these projects. These projects can be in one of the solutions, or in a completely different solution. Of course in one, or both solutions, you'll have to add a reference to the DbContext assembly, instead of the project, and keep it updated, for which you can use post-build scripts. In this way, when you recompile your solutions you'll also detect incompatible changes made for one solution which adversely affects the other.
EF6 supports several different DbContexts in the same database, so, if each of your applications had a different, non conflicting DbContext, you wouldn't have a problem. I cannot check it right know, but I think that the name of the DbContext must be different in each solution (I don't remember if the namespaces are taken into account). By non conflicting I mean that they refer to different database objects (tables, views, or whichever), of that the objects refered to by both contexts are not changed (for example master tables).

IdentityUser vs my custom user table

I have a PHP/MySQL-system that I'm porting to ASP.NET MVC5 with Azure SQL. I have a problem with grasping the concept of the new Identity solution that Microsoft has introduced. Becuase the database structure exists from the previous system, I have transfered the old MySQL database to Azure SQL. So far so good. There I have a user table with all user related data, such as username, email password etc. Becuase I wanted to continue using this table, I created the extra database fields that exists in the Identity user table. I have also created custom UserManager and other classes (MyUser, MyClaim etc.) so I am able to log in. Everything works.
Since I have a database first approach, not a code first approach, I wanted to use the User class to interact with the user table. But my UserManager returns the MyUser class (that inherits from IdentityUser), not the User class in my model. Even my dbcontext returns the MyUser class when I ask for the all the users in the User table.
Do I really need to manually update the MyUser class to replicate the User table, so if I do a change in the User table and updates my model, I have to manually update the MyUser class because the system can't/woun't use the models user class?
IdentityUser represents a default EntityFramework IUser implementation. Since you have your own existing schema, you're going to have to hand roll some classes to implement ASP.NET Identity to use your own tables.
In order to use your User class with ASP.NET Identity, you'll need to make sure it inherits from Microsoft.AspNet.Identity.IUser. After implementing IUser, update all references to MyUser with a reference to your User class. Note: You'll probably want to update your User class to something like MyAppNameUser for clarity.
After doing the above, you'll probably need to implement IUserStore so that the UserManager class can interact with your database schema.
You may want to take a look at https://github.com/raquelsa/AspNet.Identity.MySQL to get some ideas on implementing some of the ASP.NET Identity interfaces.

Avoiding duplicate entity mappings with Microsoft.AspNet.Identity 2.1.0 and multiple DbContexts

I've just started working on an existing codebase. It's an AngularJS frontend with a WebAPI backend. It's currently using Microsoft.AspNet.Identity.EntityFramework 2.1.0 and Microsoft.AspNet.Identity.Owin 2.1.0 with code first EntityFramework 6.1.1
The problem I'm having is that the codebase currently uses two database contexts, and these contexts both map to a single underlying table.
The first dbcontext is used only to support ASP.Net Identity;
public class AccountSecurityDBContext : IdentityDbContext<AccountUser, AccountRole, Guid, AccountUserLogin, AccountUserRole, AccountUserClaim>
{
...
modelBuilder.Entity<AccountUser>().ToTable("User");
...
}
where AccountUser must derive from IdentityUser due to ASP.Net Identity.requirements;
public class AccountUser : IdentityUser<Guid, AccountUserLogin, AccountUserRole, AccountUserClaim>
{
...
}
This AccountUser class is purely used to satisfy ASP.Net Identity. The the second DbContext has another mapping to the User table, used for everything other than authentication.
public class MainContextUnitOfWork : DbContext
{
...
modelBuilder.Entity<User>().ToTable("User");
...
}
So, currently, there are two classes, AccountUser and User both mapping to the same underlying User table.
This use of two DbContexts each with their own mapping to the same underlying table is causing problems. EntityFramework wants to create two migrations, one per DbContext resulting in the generation of duplicate migrations. I am aware of the add-migration --ignore option so that we can generate an empty migration for the second DbContext and that empty migration will generate a new hash of the data model in the empty migrations's designer.cs file.
Ideally I feel we should really only be using one DbContext as it's rather confusing having two DbContexts where we're using one of the DbContexts purely to support ASP.Net Identity. However I can't see how to easily refactor due to the fact that to use ASP.Net Identity the user entity must derive from IdentityUser. It's not acceptable for us to have an Entity deriving from IdentityUser to be passed up to higher layers in the appplication as this would introduce a dependency on EntityFramework in those higher layers.
My current feeling is that use of ASP.Net Identity is causing more problems than it's solving and that we'd be better off implementing our own authentication mechanism.
To reiterate. The problem lies in the fact that ASP.Net Identity forces inheritance from IdentityUser rather than allowing, for example, an implementation based on a (non-existent) IIdentityUser interface.
I've been unable to find any examples of how to overcome this.
So, the question is; Has anyone successfully used ASP.Net Identity 2.1.0 with EntityFramework 6.1.1 where you've been able to both accommodate the ASP.Net Identity requirements of using a class derived from IdentityUser and to pass a User entity up to application layers without having to reference EntityFramework in those higher layers.
Thanks in advance for any insights.
The answer turned out to be pretty simple. Although we are using EntityFramework and Asp.Net Identity, we didn't actually want to use Microsoft.AspNet.Identity.EntityFramework.
What we needed to do was just use Microsoft.AspNet.Identity and implement our own user and role store.

Categories