Multiple UserManagers - entity-framework

I'm trying to have two different UserManagers.
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<CustomUserManager>(CustomUserManager.Create);
app.CreatePerOwinContext<CustomRoleManager>(CustomRoleManager.Create);
Both ApplicationUser and CustomUser inherit IdentityUser.
How do I configure OnModelCreating to support the Roles/Claims/Logins correctly?
Am I doing something that would be considered bad practice? I just want to completely separate these two types of users. I don't want TPH since I need different required properties.
UPDATE
To further explain why I think I need this, is because I would like to have different roles and properties for these two types of users. If they share the same table, I would need a optional one-to-one relation to add properties, allow same UserNames, and who knows what else.

I made two custom UserManagers (e.g., CustomUserManager : UserManager<CustomUser>) where CustomUser inherits from IdentityUser and is specified as Table per Type with [Table("CustomUser")] on the class.
The context needs to be IdentityDbContext, or DbContext with the same DbModelBuilder settings.
Same thing goes for the roles if needed (e.g., CustomRoleManager : RoleManager<CustomRole>), they will be Table per Hierarchy. Though there isn't much use to this unless you modify the Authorize attribute and add the Claim to match the Discriminator and the role's Name.

Related

Why does Windows Identity AspNetRoles have Discriminator

I implemented Windows Identity into my application and using EF Migrations the appropriate [AspNet*] tables were added to my database. As typical in this scenario, I created an ApplicationUser class that inherits from IdentityUser. My 'ApplicationUser' class does not have any additional properties. And at that point in time I did not touch any code or classes related to Roles.
Now I am looking to add roles so I followed the same pattern as before. I created an 'ApplicationRole' class that inherits from 'IdentityRole' but did not add any addition properties.
However, and this is where my question comes in, EF migrations is trying to create a [Discriminator] column for the AspNetRoles table. Yet it never created one for the AspNetUsers table in the previous migration.
I understand the purpose of the Discriminator column so I am not questioning why it is there. I just do not understand why it is adding it for one table and not the other when both base classes were inherited by the "application" equivalent classes.
The only plausible reason I can think of is because the original IdentityRole class was used in the earlier migration and now I am trying to add a new migration that uses the base class. If so, is there a way to get EF to ignore this? There are no plans to ever create multiple classes that inherit from the base nor will I be using the base directly so the Discriminator will always contain the same value.

DDD: Concrete Type per user ROLE on Bounded Context. Identity and Access

Im stuck with designing the Identity and Access of my project against DDD.
I have Roles like Marketer, Coordinator, Planner in the system.
What I did was created concrete type for each role with their information save on table name people(name, email). and for the credentials I have users table (username, password) and table roles. Basically people and users table have the same id. (when I create user, I will also create person(people) and assign the id=user_account_id.
My problem is it seems like its not natural to check the role of the user to determine which concrete type I should instantiate. And I also have discriminator column in my people for each type. And I dont even know if creating concrete type per Role is a good idea.
I was thinking its better when I have concrete type so I can do something like
$inquiry = $marketer->makeInquiry($client, $subject);
instead of
$inquiry = new Inquiry($client, $subject, $marketer);
I also came out with idea of just using the id instead of the concrete type instance, but having problem when I need to display information about the person(people) like his name because I only have the id.
So, what is the best approach for this problem?
I am using Symfony2 and Doctrine (if it matters) but I think it is also applicable even with other technologies like ASP MVC and EF.
It's probably not a good idea to have subclasses for either Role or People (it's not entirely clear to me whether you refer to both).
For Role it isn't because the "type" of role (Planner, etc.) is just an attribute of Role, not a subtype. A role subtype would be something like a PersonRole or CompanyRole.
For People it doesn't seem a good idea because
Roles can change. Subtypes are meant to be (practically) immutable, like a Bike will always be a Vehicle of type "bike" and never turn into a Car.
It would block the possibility to assign two roles to a person by architecture. Architectural constraints are the hardest ones to change. Maybe presently it's not a question whether a person can have multiple roles, but in the future it may.
When it comes to differences of behavior based on a person's role you should consider other behavioral patterns than inheritance. Also look at composition over inheritance.

Entity Framework, Link tables and mapping multiple tables to a single entity

I have an Entity called "Product", this entity, through table mapping, merges 6 tables that have a 1 to 1..0 relationship with "Products". This all works wonderfully. There is another property I want to add to "Products", which is sBBR_rate, this value is not in a table that has a direct 1 to 1..0 relationship, it is related through a link table as below:
When I import the two tables into the EDM, I can't see a way in the "Mapping Details" of
"Product" to reference the sBBR_rate. I can reference RatesLink and link that to the "Products" primary key, however, I cannot reference the BBR table.
The methods I can think of to work "around" this is are as follows:
Create a view, reference the view in the EDM.
Create an SP and use a function import to retrieve the BBR when it is required.
Create a "Rates" entity in the EDM that can then draw down the sBBR_rate into it. Navigate to the Products BBR through Product.Rates.sBBR_rate.
Is there a better way I can do this that doesn't feel so much like a fudge? Perhaps by directly editing the XML of the Mapping or Conceptual layers of the EDM?
Thanks for your input.
Because the multiplicities on the Product -> RatesLink and RatesLink -> BBR relationships are 0 to 1, you should be able to access the sBBR_rate from a Product instance like this:
myProductInstance.RatesLink.BBR.sBBR_rate
I can see on the EDM screenshot that RatesLink has a Product and BBR property, which would indicate this should be available - is it?
On a side note, if it makes sense for the sBBR_rate property to commonly be accessed directly from Product, you might want to follow the law of demeter and create a property on Product which returns it directly.
The model we are using is to extend entities by using partial classes which we've found useful so we can get additional properties in the autogenerated classes (we are using a POCO T4 template to autogen but I believe this would work just as well with the default entity object generation).
So we would have
//.. this one is from the T4 template
public partial class Product
{
//.. all the autogenerated methods
}
and in a separate file that isn't autogened
//.. now in a separate file created by me
public partial class Product
{
//.. my custom properties and methods to make the entities more usable
public string BBRRate
{
get {return this.RatesLink.BBR.sBBR_rate; }
}
}
This means that I can just do
myProduct.BBRRte
I know there are other ways to do this by amending the edmx file but this one we found easy to implement. You just need to watch performance because you are potentially loading extra data. Also we did this with LazyLoading turned on but with more work you wouldn't have to
We also experimented with hooking into the ObjectMaterialized event in the ObjectContext class to preload some of these properties. Using a custom interface i.e. IMaterialisable we could check if the object was of that type then call a method (Materialise) to prepopulate some of the properties. This seems like a good idea but we didn't widely use it - it was easy to load up too much stuff. If you do the load on the properties in the partial classes then it becomes more efficient. Just my experience.
Anyway - as always an interesting question and good luck again with your dev.
EDIT
There is a rule that everything in the store layer must be represented some way in your conceptual layer. Therefore removing the tables from the conceptual layer but bring through some of the properties I don't think will work in it's gross form. Therefore I can think of two further options
Create a View on the database and bring that in as you have already mentioned. TBH this is what I would do.
Use the DefiningQuery element directly in your xml (the store layer) and map the query through to a custom entity of your exact design. Julie Lerman describes this as the ultimate escape hatch for Entity Framework.
Remember though - if you manual amend the XML in point 2 then you lose the ability to automatically update the module through the IDE
I ended up creating a view and then linking this view in the EDM, this worked a treat.

ASP.Net MVC2 Validate two ViewModels of the same class differently using DataAnnotations

I'm using DataAnnotations for validation of a custom class (LINQ to SQL auto generated) using the MetadataType tag on top of the class. I'm loving DataAnnotations and it works well in simple, common scenarios. E.g.
[MetadataType(typeof(Person_Validation))]
public class Person
But what if you need to have two different sets of validation rules applied to the class in different scenarios???
My situation: Some fields are mandatory on the www public-facing site, but not mandatory on the internal admin site. But both sites have a View which "Creates New" of the same object/class.
This is where it becomes DataAnnotations HELL surfaces..
I've tried using two different ViewModels with different validation applied to each of them, two classes that inherit from Person with different validation applied to each of them. But all roads seem to conflict with DRY principals and you end up somewhere along the line having the totally respecify all properties for the underlying class structure. You don't have to do this when you just have one validation rule set. So it very quickly becomes hell and not practical for complex objects.
Is this possible using DataAnnotations and what is the best DRY architecture?
Not sure what you mean by 'virtually duplicate and manually set each and every property manually in the original underlying class'. I've never liked the idea of buddy classes, and would personally recommend different view models for Admin and Public site (with appropriate validation set on each), and then mapping between the models using AutoMapper.
UPDATE:
Regading Automapper, the basic usage is something like this:
First you have to define your mappings. This lets automapper figure out in advance how to map objects. You only need to do this once in the application, so a good place to do this in an ASP.NET app is in Application_Start() in Global.asax. For each pair of classes you want to map between, call: Mapper.CreateMap<SourceType, DestinationType>();
Then, in your application code to do the map you just use:
var destinationObject = Mapper.Map<SourceType, DestinationType>(sourceOjbect);

Entity Framework: Inheritance, change object type

Let's say, I have 2 classes in the model: User (mapped to USERS table) and PrivilegedUser (inherits User, additional info is stored in PRIVILEGEDUSERS table).
Now, I have a row in USERS (and instance of User) and need to convert that user to PrivilegedUser (i.e. to create a record in PRIVILEGEDUSERS with the same Id). Is there a way to do this without Delete/Insert?
The problem is you don't have PRIVILEGEDUSERS representation in the model, so you cannot create only that part of PrivilegedUser.
It was just an example. PrivilegedUser may have some discount or personal manager or whatever in addition to ordinary User properties. In the same time, there are other tables which need to reference users regardless of concrete User type. I've implemented it using Table-per-Type inheritance mode. In the database level it's very simple to convert users from one type to another (you just need to insert or delete record from extension table). But in EF you have only UserSet which stores both User and PrivilegedUser objects. That's why I ask is it possible to replace existing User object with PrivilegedUser keeping existing Id and without deleting record from USERS table.
No you cannot.
As explained by this article, EF (3.5) does not support this feature. You must use stored procedure to accomplish this.
You need to change your world view. Your view is that you have standard users with standard privileges and super users with additional privileges. The privileges aren't enumerated, they are implicit.
The new world view is that you maintain a list of all privileges, both standard and super and then in a mapping table you create a many to many map of which users have which privileges. When a user is granted super privileges, you just add mappings for the appropriate privileges to the mapping table. You don't need a PrivilegedUser class, just a list of privileges in the User class. The privileges may be either standard or super.
It seems wrong that you have two tables representing users.
Would it not be better to have a Users table (for all users) and then a UserPrivileges table, representing what they are allowed to do? This way, no deletes/Inserts are needed, and you can reference just one table for users.
A third table can be used to represent the actual privileges.
Users
Id Username ...
UserPrivileges
UserId PrivilegeId
Privileges
Id Description
Regarding inheritance in EF take a look at this site, which explains the three different ways to use inheritance in EF.
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/01/20/entity-framework-inheritance-types.aspx
As said, you cannot. Either by stored procedures or by custom insert/update query. I had similar problem, now I'm using solution that i described in this answer: https://stackoverflow.com/a/28380804/2424989